Reputation: 4222
I'm using Ember.js to display a list of customers. Inside this template, I have a modal to create new customers. Now, when creating invalid customers (e.g. duplicate name), the errors should be shown in the template. How can I get this to work?
model
Docket.Customer = DS.Model.extend({
name: DS.attr('string'),
initial: DS.attr('string'),
description: DS.attr('string'),
errors: {},
becameInvalid: function(errors) {
this.set('errors', errors.get('errors'));
console.log(this.get('errors'));
}
});
console output
template
<h1>Customers<button data-uk-modal="{target:'#customer-modal'}" class="icon-plus">New customer</button></h1>
<div id="customer-modal" class="uk-modal">
<div class="uk-modal-dialog uk-modal-dialog-slide">
<a class="uk-modal-close uk-close"></a>
<form class="uk-form" {{action "save" on="submit"}}>
<fieldset>
<legend>New customer</legend>
<div class="uk-form-row">
{{view Ember.TextField valueBinding="name" name="name" class="uk-width-1-1" placeholder="Name" required="" }}
{{#if errors}}foo{{/if}}
{{#if errors.name}}{{errors.name}}{{/if}}
</div>
<div class="uk-form-row">
{{view Ember.TextField valueBinding="initial" name="initial" class="uk-width-1-1" placeholder="Initial" required="" }}
</div>
<div class="uk-form-row">
{{view Ember.TextArea valueBinding="description" name="description" class="uk-width-1-1" placeholder="Description"}}
</div>
<div class="uk-form-row">
<button type="submit" class="icon-check">Save</button>
</div>
</fieldset>
</form>
</div>
</div>
<ul class="entries">
{{#each}}
<li>
<div class="actions">
<button {{action "remove" id}} class="icon-close"></button>
</div>
<div class="link" {{action "edit" id}} data-uk-modal="{target:'#customer-modal'}">
<span class="initial">{{initial}}</span>{{name}}
</div>
</li>
{{else}}
<li>No customers</li>
{{/each}}
</ul>
Upvotes: 4
Views: 5141
Reputation: 4222
I figured it out:
setup
model
Docket.Customer = DS.Model.extend({
name: DS.attr('string'),
initial: DS.attr('string'),
description: DS.attr('string'),
number: DS.attr('string'),
archived: DS.attr('boolean')
});
controller
var _this = this;
// Create new record
var customer = this.store.createRecord('customer', data);
// Check for server errors (422) when saving
customer.save().then(function(){
_this.resetAndCloseForm(form);
}, function(response){
_this.set('errors',response.errors);
});
route
model: function() {
this.store.find('customer');
return this.store.filter('customer', function(customer) {
// prevent Ember to insert new elements to the DOM if they are invalid
// .get('isValid') returns always true, I think this is a bug, so I'm checking the ID
return customer.get('id')
})
}
template
{{#if errors}}{{errors.name}}{{/if}}
Upvotes: 2
Reputation: 536
You should consider moving your validations to the controller
. Form validations and validations in general are very contextual. Customer
model might have different set of validations depending on which part of your app you're in.
If you decide to move validations to the controller
, you would need to create an observer that is going to watch the changes of a particular property/properties and run validations accordingly.
Note: I'm talking about client side validations (doesn't involve talking to the server before validations conditions are met), not server side ones.
App.CustomerController = Ember.ObjectController.extend({
errors: [],
runNameValidation: function() {
// run validations for 'name'
// if validations fail, push error to 'errors' array
// on the controller
}.observes('model.name')
});
There's a validations library that takes care of it for you (it abstracts out validations bit and wraps it into a validations mixin for better reuse). Also, if you use for form specifically, you should consider looking at easyForm.
Update:
If you want to use server side validations, then all you need to add to your template is:
{{model.errors}}
When you try to save ED model and it server fails to do it, model
is going to have errors
array which you can use. Also, I would suggest creating the errors
component, instead of creating the errors
helper.
Upvotes: 3
Reputation: 19128
You can create a custom handlebars helper, like the following:
Ember.Handlebars.helper('show-errors', function(errors) {
var html = '';
if (errors) {
html += '<ul>';
$.each(errors, function(key, values) {
html += '<li>' + key + ' - ' + values.join(',') + '</li>'
});
html += '</ul>'
}
return html.htmlSafe();
})
So just use {{show-errors recordInstance.errors}}
in some template to use it.
In the first moment, there isn't errors so nothing will be displayed. When your record has a error, errors
hash will be populed and the template will be updated.
Give a look in this fiddle http://jsfiddle.net/marciojunior/vh6aL/
Upvotes: 3