Knockout.js: формат ввода времени и ограничение значения

Когда я связываю числовые данные в моей модели представления с использованием нокаута, он отображается правильно, но изменяет тип данных на строку, если пользователь меняет значение входного тега. Проблема с отправкой строки заключается в том, что сервер ожидает числовое значение, не имеющее неявного преобразования.

Любой способ сообщить нокауту сохранить тип данных исходного значения свойства?

Мой примерный код, совпадающий с именами модели представления, с именами входных тегов. Я использую ненавязчивый нокаут для выполнения привязок, который отлично работает.

// Bind the first object returned to the first view model object
// FNS is the namespace, VM is the view model
FNS.VM.Items[0] = ko.mapping.fromJS(data.Items[0]);

// For each property found, find the matching input and bind it
$.each(FNS.VM.Items[0], function (indexInArray, valueOfElement) {
    var attrName = indexInArray;
    var attrValue;
    if (typeof valueOfElement == "function")
        attrValue = valueOfElement();
    else
        attrValue = valueOfElement;

    var a = $('input[name="' + attrName + '"][type="checkbox"]');
    if (a.length)
        a.dataBind({ checked: 'VM.Items[0].' + attrName });

    var b = $('input[name="' + attrName + '"][type="radio"]');
    if (b.length)
        b.dataBind({ checked: 'VM.Items[0].' + attrName });

    var c = $('input[name="' + attrName + '"][type="text"]');
    if (c.length)
        c.dataBind({ value: 'VM.Items[0].' + attrName });
});
ko.applyBindings(FNS);

Ответ 1

Вот поток с несколькими разными методами, чтобы сохранить числовое значение: https://groups.google.com/d/topic/knockoutjs/SPrzcgddoY4/discussion

Один из вариантов заключается в том, чтобы включить эту проблему в вашу модель представления и создать numericObservable для использования вместо обычного наблюдаемого. Это может выглядеть так:

ko.numericObservable = function(initialValue) {
    var _actual = ko.observable(initialValue);

    var result = ko.dependentObservable({
        read: function() {
            return _actual();
        },
        write: function(newValue) {
            var parsedValue = parseFloat(newValue);
            _actual(isNaN(parsedValue) ? newValue : parsedValue);
        }
    });

    return result;
};

Пример: http://jsfiddle.net/rniemeyer/RJbdS/

Другой вариант - обработать это с помощью специальной привязки. Вместо использования привязки value вы можете определить привязку numericValue и использовать ее вместо этого. Это может выглядеть так:

ko.bindingHandlers.numericValue = {
    init : function(element, valueAccessor, allBindings, data, context) {
        var interceptor = ko.computed({
            read: function() {
                return ko.unwrap(valueAccessor());
            },
            write: function(value) {
                if (!isNaN(value)) {
                    valueAccessor()(parseFloat(value));
                }                
            },
            disposeWhenNodeIsRemoved: element 
        });

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

Пример: http://jsfiddle.net/rniemeyer/wtZ9X/