How to override a parent property in ember.js? (Specifically number input's behaviour)

淺唱寂寞╮ 提交于 2019-12-11 05:49:50

问题


I want to write a new component that extends Ember Input as number input. When users of this class binds their values to value property of number-input-component, they should only get a number (or NaN for invalid values). In Ember Input, value has an attribute binding.

I've defined a computed property named "value" on number-input-component as following:

value:Ember.computed({
    get:function(key){
       let htmlValue = this.get('htmlvalue');
       return this.sanitize(htmlValue);
    },
    set:function (key, htmlvalue){
       this.set('htmlvalue', htmlvalue);

       if(this.get('onUpdate')) {
          this.get('onUpdate')(this.sanitize(htmlvalue));
       }
       return this.sanitize(htmlvalue);
    }
}),

It works as expected but it's not working in two-way binding. (Actually it is ok for DDAU. But it should work in two-way bindings.)

Note: I know that I can supply another property such as "numericValue" (shown as here) so that users can bind their values to "numericValue". But I don't want to confuse users with both value and numericValue.

UPDATE:

While typing to the field, any typo shouldn't reset the value. For example while user is trying to write "123456789" and accidentally press "12345678p" should not cause the input reset. Neither displaying an error message nor reseting the value is not a responsibility of the component when value is invalid.

There is a fiddle you can see: Ember-Twiddle


回答1:


Another way would be to overwrite the _elementValueDidChange() method. You can get the current DOM value by this.readDOMAttr('value'), do your sanitizing and finally call this.set('value', sanitizedValue). This is how Ember internally changes the value property.




回答2:


You can write an observer of the value property and when it is changed, replace it with the sanitized version:

valueWatcher() {
    this.set('value' this.sanitize(this.get('value')));
}.observes('value')

Ember will prevent the race condition when an observer modifies the property it watches.




回答3:


I've found a solution using _elementDidChange suggested in @jcbvm's solution. Also override attributeBindings to manage the screen value.

Here it is:

import Ember from 'ember';

export default Ember.TextField.extend({
  type:'text',//hey! this is text!

  init(){
    this._super(...arguments);
    let arr = this.get('attributeBindings');
    arr.removeObject('value');
    arr.pushObject('val:value');
  },

  val: Ember.computed('domValue', 'value', function() {
    let value = this.get('value');
    //detect whether the update is trigger by dom or by users of this class:
    if(!Number.isNaN(value) && this.sanitize(this.get('domValue')) !== value){
      return value;
    }
    return this.get('domValue');
  }),

  _elementValueDidChange(){
    let domValue = this.readDOMAttr('value');
    let value = this.sanitize(domValue);
    if(this.sanitize(this.get('domValue')) !== value){
        this.set('domValue', domValue);      
    }
    this.set('value', value);
  },


  sanitize:function(value){
    if(value === ''){
      return Number.NaN;
    }
    return Number(value);
  }
});

The reason of using type=text is html5 number inputs' sanitization algorithm. input type=number component returns empty string for invalid values on Chrome, Firefox and Edge (not IE).Reference for sanitization from W3C.

Cons of this solution:

  • Overrides _elementDidChange
  • Modifies attributeBindings. (Maybe parent classes depends on this value.)


来源:https://stackoverflow.com/questions/36941190/how-to-override-a-parent-property-in-ember-js-specifically-number-inputs-beha

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!