Ember.js: Number attributes don't convert values properly when used with input helpers

Created on 18 May 2015  ·  10Comments  ·  Source: emberjs/ember.js

In the example here: http://emberjs.jsbin.com/yiqogukoqe/2/edit, a model containing a numeric field has the field change to a string once edited from an input helper. Is this the expected behavior? If it is, I couldn't find any place in the guides discouraging this usage pattern, and in any case it is unintuitive and misleading IMO

Most helpful comment

Just got bit by this. In my case I was relying on the model's hasDirtyAttributes flag to toggle a save button. Every time I clicked in the input without changing the value the flag would get set to true and I could not for the life of me figure it out. Eventually I output the results of changedAttributes() and realized that when you click on the input, the integer changes to a string causing the hasDirtyAttributes flag to trigger even though from the UI nothing looks to have changed.

Thought I'd mention it here in case someone else runs into the issue. (my input is of type number)

All 10 comments

This is the browser behavior and not one that Ember is adding to the mix. We are calling .value on the <input> element and that is returning a string.

See this plain HTML + JS demo.


If you are asking why Ember Data does not automatically convert the values back into a number for you when the attribute is set, then take a look at https://github.com/emberjs/data/pull/1854 which attempted to add this auto-conversion when the attribute was set. The last comment by @igorT is almost certain still true:

I think we decided that this path is too hard to do properly and that transforming data coming into the record from users code is really user's responsibility. I am not sure that doing this automagically at the record layer even works properly, as it would probably create issue in different parts of your app, for example if you transform a select value without your select knowing about it, seems like your selection could easily get mismatched with the backing data.

@rwjblue ok, so what is the recommended practice in my case? Add a computed property that forces the value to an integer? I'm just trying to understand the Ember way of accomplishing this...

@rwjblue I admit, I'm pretty stupid, but I just can't figure out a simple way to set an attribute to an integer using an {{input}}. I'm with @vmalloc above. Should we set to a property then observe that property, cast to integer, then set the value of the attr? Could we check if the input has a type="number" attribute and parseInt if so?

I'm totally +1 on that one. The current behavior doesn't make sense.
On יום ה׳, 6 באוג׳ 2015 at 23:30 Ben Borowski [email protected]
wrote:

@rwjblue https://github.com/rwjblue I admit, I'm pretty stupid, but I
just can't figure out a simple way to set an attribute to an integer using
an {{input}}. I'm with @vmalloc https://github.com/vmalloc above.
Should we set to a property then observe that property, cast to integer,
then set the value of the attr? Could we check if the input has a
type="number" attribute and parseInt if so?


Reply to this email directly or view it on GitHub
https://github.com/emberjs/ember.js/issues/11209#issuecomment-128498505.

@vmalloc Here's my quick hacky workaround:

 ordinal: 1,
 ordinalChanged: Ember.observer('ordinal', function() {
    this.set('model.ordinal', parseInt(this.get('ordinal')));
 })

then set {{input value=ordinal}}instead of{{input value=model.ordinal}}`

In this case, I'm in a component, so also need to set initial value of ordinal on didInitAttrs or didReceiveAttrs I think. There must be a better way.

This might work a little better:

  ordinalAsString: computed('model.ordinal', {
    get(){
      return "" + this.get('model.ordinal');
    },
    set(_, value){
      this.set('model.ordinal', parseInt(value));
    }
  })
{{input value=ordinalAsString}}

Really, though, we should be able to do this:

{{input value=model.ordinal transform="number"}}

@michaeljbishop at that level, I think you'd just make a number-input component, yeah? instead of transform. bundle all that stuff up in a reusable component.

That would work, but I find it a little distasteful because for any type of value that you wanted to transform, you'd have to make a new special class for it. Adding support for a transform attribute on the standard input helper would mean you could inject any standard Ember transform onto any input, allowing you to compose different objects on the fly to create behavior.

Cocoa bindings does exactly this and it works great!

https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ValueTransformers/Concepts/TransformersRole.html

@michaeljbishop indeed, reminds me of Flex mxml! You should make an ember addon.

Just got bit by this. In my case I was relying on the model's hasDirtyAttributes flag to toggle a save button. Every time I clicked in the input without changing the value the flag would get set to true and I could not for the life of me figure it out. Eventually I output the results of changedAttributes() and realized that when you click on the input, the integer changes to a string causing the hasDirtyAttributes flag to trigger even though from the UI nothing looks to have changed.

Thought I'd mention it here in case someone else runs into the issue. (my input is of type number)

Was this page helpful?
0 / 5 - 0 ratings