Как переопределить родительское свойство в ember.js? (В частности, поведение ввода чисел)

Я хочу написать новый компонент, который расширяет Ember Input как ввод числа. Когда пользователи этого класса связывают свои значения с value свойство number-input-component, они должны получать только число (или NaN для недопустимых значений). В Ember Input значение имеет привязку атрибута.

Я определил вычисляемое свойство с именем "value" для number-input-component следующим образом:

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

Он работает как положено, но не работает в двухстороннем связывании. (На самом деле это нормально для DDAU. ​​Но он должен работать в двухстороннем связывании.)

Примечание. Я знаю, что могу предоставить другое свойство, такое как "numericValue" (показано здесь), чтобы пользователи могли связывать свои значения с "numericValue". Но я не хочу путать пользователей со значением и numericValue.

ОБНОВИТЬ:

При вводе в поле любая опечатка не должна сбрасывать значение. Например, когда пользователь пытается написать "123456789" и случайно нажать "12345678p", это не должно вызывать сброс ввода. Ни отображение сообщения об ошибке, ни сброс значения не являются обязанностью компонента, если значение недопустимо.

Вы можете увидеть скрипку: Ember-Twiddle

3 ответа

Другим способом было бы перезаписать _elementValueDidChange() метод. Вы можете получить текущее значение DOM, this.readDOMAttr('value')Занимайтесь дезинфекцией и наконец звоните this.set('value', sanitizedValue), Вот как Эмбер внутренне меняет value имущество.

Вы можете написать наблюдателя value свойство и когда оно изменено, замените его очищенной версией:

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

Ember предотвратит состояние гонки, когда наблюдатель изменяет свойство, за которым он наблюдает.

Я нашел решение, используя _elementDidChange предложено в решении @jcbvm. Также переопределите 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). Ссылка для очистки из W3C.

Минусы этого решения:

  • Переопределение _elementDidChange
  • Изменяет attributeBindings. (Возможно, родительские классы зависят от этого значения.)
Другие вопросы по тегам