Привязка KnockoutJS путается с маской ввода

Я пытаюсь применить маску ввода к полю телефона. Это работает, пока я не применяю привязку KnockoutJS, которая удаляет маску, пока поле не получит фокус.

Не работает: http://jsfiddle.net/8r6fe/

$('[data-mask]').each(function () {
    console.log('mask');
    $this = $(this);
    var mask = $this.attr('data-mask') || 'error...', mask_placeholder = $this.attr('data-mask-placeholder') || 'X';

    $this.mask(mask, {
        placeholder: mask_placeholder
    });
})


var ViewModel = function() {
    this.firstName = ko.observable("");
    this.lastName = ko.observable("");
    this.phone = ko.observable("");

    this.fullName = ko.computed(function() {
        return this.firstName() + " " + this.lastName();
    }, this);

    this.firstName('John');
    this.lastName('Doe');
    this.phone('1231231234');
}; 
ko.applyBindings(new ViewModel());

Работает: http://jsfiddle.net/gxhjn/

var ViewModel = function(first, last) {
    this.firstName = ko.observable(first);
    this.lastName = ko.observable(last);

    this.fullName = ko.computed(function() {
        // Knockout tracks dependencies automatically. It knows that fullName depends on firstName and lastName, because these get called when evaluating fullName.
        return this.firstName() + " " + this.lastName();
    }, this);
};

ko.applyBindings(new ViewModel("Planet", "Earth")); // This makes Knockout get to work

$('[data-mask]').each(function () {
    console.log('mask');
    $this = $(this);
    var mask = $this.attr('data-mask') || 'error...', mask_placeholder = $this.attr('data-mask-placeholder') || 'X';

    $this.mask(mask, {
        placeholder: mask_placeholder
    });
})

person Mike Cole    schedule 11.03.2014    source источник


Ответы (1)


Я не думаю, что это проблема нокаута, но проблема в том, как разработан плагин маскированного ввода: ваше начальное значение должно соответствовать критериям маски. Даже если вы избавитесь от нокаута и просто используете функцию jQuery val() для установки значения «1231231234», вы увидите то же поведение.

ОБНОВЛЕНИЕ

Извините, пропустил вашу ссылку "работы". Я собирался предложить собственный обработчик привязки в первую очередь. Похоже, это путь. Он применяет маскирование после обновления текста с помощью нокаута, а затем обновляет модель представления новым замаскированным значением (если это то, что вы хотите):

ko.bindingHandlers.maskedInput = {
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        ko.bindingHandlers.value.init(element, valueAccessor, allBindings, viewModel, bindingContext);
    },
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        ko.bindingHandlers.value.update(element, valueAccessor, allBindings, viewModel, bindingContext);
        $(element).mask(allBindings.get('mask'));
        valueAccessor()($(element).val());
    }
};

Вот ваша обновленная скрипта: http://jsfiddle.net/8r6fe/3/

person PatrickSteele    schedule 11.03.2014
comment
Проверьте ссылку на мои работы. Значение имеет неправильный формат, но плагин правильно его маскирует. В ссылке не работает, если бы я переместил маску ввода js после привязки нокаута, она работает правильно. - person Mike Cole; 12.03.2014
comment
Добавлен пользовательский обработчик привязки, чтобы показать, как это можно сделать. - person PatrickSteele; 12.03.2014
comment
Небольшая модификация: если я выполняю обработчик при инициализации вместо обновления, он обрабатывает случаи, когда мой результат ajax возвращается нулевым, и привязка не выполняется. - person Mike Cole; 12.03.2014
comment
Добавление обработчика, похоже, нарушает двустороннюю привязку. Даже когда я удаляю событие обновления и оставляю пустой обработчик, он не обновляет модель представления. Вы можете увидеть в своем примере, если вы обновите значение и отключите телефон. - person Mike Cole; 12.03.2014
comment
Прости, Майк. Без обработчика инициализации ни один обработчик событий не подключается к изменениям в текстовом поле. Я добавил это, и теперь это работает. - person PatrickSteele; 13.03.2014