Knockout.js Расширение привязки значения с помощью перехватчика

Кажется, это распространенный подход к очистке/проверке/форматированию данных с нокаутом при привязке к полю ввода, он создает повторно используемую пользовательскую привязку, которая использует вычисляемый наблюдаемый объект. Он в основном расширяет привязку значения по умолчанию, включая перехватчик, который форматирует/дезинфицирует/проверяет ввод перед записью/чтением.

ko.bindingHandlers.amountValue = {
  init: function (element, valueAccessor, allBindingsAccessor) {
    var underlyingObservable = valueAccessor();

    var interceptor = ko.computed({
      read: function () {
        // this function does get called, but it's return value is not used as the value of the textbox.
        // the raw value from the underlyingObservable is still used, no dollar sign added. It seems like 
        // this read function is completely useless, and isn't used at all
        return "$" + underlyingObservable();
      },

      write: function (newValue) {
        var current = underlyingObservable(),
            valueToWrite = Math.round(parseFloat(newValue.replace("$", "")) * 100) / 100;

        if (valueToWrite !== current) {
          // for some reason, if a user enters 20.00000 for example, the value written to the observable
          // is 20, but the original value they entered (20.00000) is still shown in the text box.
          underlyingObservable(valueToWrite);
        } else {
          if (newValue !== current.toString())
            underlyingObservable.valueHasMutated();
        }
      }
    });

    ko.bindingHandlers.value.init(element, function () { return interceptor }, allBindingsAccessor);
  },

  update: ko.bindingHandlers.value.update
};

Пример jsFiddle: http://jsfiddle.net/6wxb5/1/

Я что-то пропустил? Я видел, как этот метод используется повсеместно, но, похоже, он не работает полностью. Функция чтения кажется совершенно бесполезной, поскольку она вообще не используется ..., а в функции записи ввод «23.0000» изменяет записанное значение на 23, но значения текстового поля не обновляются.


person wired_in    schedule 28.09.2012    source источник


Ответы (1)


Проблема возникает из-за части update вашей пользовательской привязки. Эта часть обновит поле на основе исходного значения модели. Таким образом, обработчик событий, прикрепленный к init, отправит новое значение через ваш вычисляемый объект для записи, но обновление поля на самом деле происходит в update.

Один из вариантов — применить привязку значения из вашей функции init и пропустить функцию update, например:

ko.bindingHandlers.amountValue = {
  init: function (element, valueAccessor, allBindingsAccessor) {
    var underlyingObservable = valueAccessor();

    var interceptor = ko.computed({
      read: function () {
        // this function does get called, but it's return value is not used as the value of the textbox.
        // the raw value from the underlyingObservable, or the actual value the user entered is used instead, no   
        // dollar sign added. It seems like this read function is completely useless, and isn't used at all
        return "$" + underlyingObservable();
      },

      write: function (newValue) {
        var current = underlyingObservable(),
            valueToWrite = Math.round(parseFloat(newValue.replace("$", "")) * 100) / 100;

        if (valueToWrite !== current) {
          // for some reason, if a user enters 20.00000 for example, the value written to the observable
          // is 20, but the original value they entered (20.00000) is still shown in the text box.
          underlyingObservable(valueToWrite);
        } else {
          if (newValue !== current.toString())
            underlyingObservable.valueHasMutated();
        }
      }
    });

      ko.applyBindingsToNode(element, { value: interceptor });
  }
};

Обновленная скрипта: http://jsfiddle.net/rniemeyer/Sr8Ev/

person RP Niemeyer    schedule 28.09.2012
comment
Спасибо, это расстроило ;) - person wired_in; 29.09.2012