A simple situation with unexpected results
Before I get to my question, some context. I have an ember-data project
DEBUG: -------------------------------
DEBUG: Ember : 1.11.1
DEBUG: Ember Data : 1.0.0-beta.16.1
DEBUG: jQuery : 1.11.2
DEBUG: Ember Simple Auth : 0.7.3
DEBUG: -------------------------------
An Ember-data model
I have a simple model containing some string attributes and some number attributes. This is my app\models\simplemodel.js
import DS from "ember-data";
export default DS.Model.extend({
code: DS.attr('string'),
description: DS.attr('string'),
a_number: DS.attr('number'),
another_number: DS.attr('number'),
related_stuff: DS.hasMany('someothermodel', {async: true})
});
A handlebars template with bound <input type="number">
elements
I have a template in which I set the number parameters with a bound <input type="number">
element.
<header>
<h2>{{model.code}}</h2>
<h2>{{textarea value=model.description placeholder="description"}}</h2>
</header>
<section>
<p>
<label>A number: </label>{{input type="number" value=model.a_number}}
<label>Another number: </label>{{input type="number" value=model.another_number}}
{{#if model.isDirty}}
<button {{action 'save'}}>Save</button>
{{/if}}
</p>
</section>
The problem/Unexpected behaviour
When I change the value of the <input type="number">
elements the save button appears as expected. However, when I reset the value back to the original value the save button remains. The model isDirty
is still true even though the values match the original values.
Possible explanation
Now, I understand that the <input>
element will store its content as a string rather than a number. Presumably, when I change the value of the bound input
it sets the bound model attribute to its value. It could be that the original value was say 1
but the by using the <input>
element I am changing the value to "1"
. However, the model explicitly declares this attribute to be a DS.attr('number')
. Indeed, when I save the model it dutifully sends a number in the payload to the server.
{"simplemodel":{"code":"34735337888888","description":"Some description","a_number":4,"another_number":5}}
This is expected, ember-data deals with communication with the server and has cast the DS.attr('number')
attributes to numbers. So I guess the actual value of the model attribute before it is sent to the server is still a string and hence the model isDirty
.
The question
Is my explanation correct and is there a way to avoid this problem?
Possible solutions
I can see two obvious ways to handle this.
- Make a version of the input element that transparently casts strings to numbers - I have tried this with no luck - probably because I don't understand how ember works.
- Have the model cast values to the appropriate type automatically.
My instinct would be to go with 1
as 2
feels like it would be more likely to produce unexpected behaviour.
My attempt
I tried to produce a component to use for all input elements bound to numbers.
import Ember from 'ember';
export default Ember.Component.extend({
attributeBindings: ['value', 'type'],
tagName: 'input',
type: 'number',
number: null,
value: function() {
var number = this.get('number');
return number;
}.property('number'),
change: function() {
var value = this.$().val();
this.set('number', parseFloat(value));
}
});
When I used this, the isDirty
flag was not set at all even when the value of my component was changed. I don't understand this anyway, it was adapted from something I've been using for date fields. Do I need to do something else here?
Aucun commentaire:
Enregistrer un commentaire