2016-04-29 37 views
1

我想写一个扩展Ember输入作为数字输入的新组件。当这个类的用户将它们的值绑定到value属性数字输入组件时,它们应该只能得到一个数(或NaN表示无效值)。在Ember Input中,值有一个属性绑定。如何覆盖ember.js中的父属性? (具体数字输入的行为)

我定义上号输入分量名为“价值”的一个计算属性如下:

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); 
    } 
}), 

它工作正常,但它不是在双向绑定工作。 (其实这是OK的DDAU但应该在双向绑定工作。)

: 我知道,我可以提供其他属性,如“numericValue”(如图here),以便用户可以将它们的值绑定到“numericValue”。但我不想混淆numericValue的用户。

UPDATE:

打字时到现场,任何错字应不会重置价值。例如,当用户试图写入“123456789”,并意外按“12345678p”不应导致输入重置。当值无效时,显示错误消息或重置值都不是组件的责任。

有一个小提琴,你可以看到:Ember-Twiddle

回答

0

你可以写value属性的观察者,当它改变时,用消毒的版本来替换它:

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

灰烬将阻止当观察者修改它所观察的财产时的竞争条件。

+0

但在字段中输入时闪烁。我会更新我的问题。 – ykaragol

1

另一种方法是覆盖_elementValueDidChange()方法。您可以通过this.readDOMAttr('value')获得当前DOM值,进行消毒并最终致电this.set('value', sanitizedValue)。这是Ember内部如何更改value属性。

+0

是的,这样做可以完全解决问题。但由于下划线,我对此没有信心。它以某种方式私人/不可靠的功能? – ykaragol

+1

它是私人的,但是因为我们覆盖了输入组件的默认行为,所以我认为这不是一件坏事。我在我的应用中使用类似的东西,从来没有任何麻烦。 – jcbvm

0

我在@ jcbvm的解决方案中找到了使用_elementDidChange建议的解决方案。还要覆盖attributeBindings来管理屏幕值。

这:

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); 
    } 
}); 

使用type=text是HTML5号输入消毒算法的原因。 input type=number组件在Chrome,Firefox和Edge(不是IE)上为无效值返回空字符串。用于清理的参考from W3C。这种解决方案的

缺点:

  • 重写_elementDidChange
  • :修改attributeBindings。 (也许父类依赖于这个值。)