Пользовательская проверка, вызывающая срабатывание вычисленных значений
Для быстрого просмотра моей проблемы я сделал рабочий jsFiddle здесь:
В KnockoutJS я сделал собственный валидатор расширителя, чтобы проверить, является ли формат ввода в формате ЧЧММ. Если это так, он возвращает новое значение, в противном случае он вернет его к старому значению, это в настоящее время работает.
ko.extenders.acValidTimeHHMM = function (target, options) {
var result = ko.computed({
read: target,
write: function (newValue) {
var re = /^([0-9]|0[0-9]|1[0-9]|2[0-3])[0-5][0-9]$/;
if (!re.test(newValue)) {
target.notifySubscribers(target());
//Time not in correct format return old time
return;
}
target(newValue);
}
}).extend({ notify: 'always' });
result(target());
return result;
};
Проблема, с которой я столкнулся, заключается в том, что я обновляю свою базу данных, когда значение изменяется с использованием вычисленного значения. Однако это также срабатывает, когда я сбрасываю значение обратно к его оригиналу, используя мой валидатор. (Метод, основанный на технике грязного флага Райана Ральфа)
self.update = ko.computed(function () {
self.timeOne();
self.timeTwo();
alert("Fired");
});
Проблема, очевидно, заключается в строке target.notifySubscribeers(target()); в моем валидаторе. Однако без этой строки я не могу сбросить значение до его старого значения, и я не могу найти другой способ сделать это.
Так что это срабатывает только тогда, когда значение действительно меняется, а не валидатор, сбрасывающий его. JsFiddle точно демонстрирует мою проблему и может быть использован для создания рабочей версии (надеюсь). Я знаю, что в настоящее время она также запускается при загрузке страницы.
1 ответ
Проблема, с которой я столкнулся, заключается в том, что я обновляю свою базу данных, когда значение изменяется с использованием вычисленного значения
Я не знаю всей вашей логики, но я не думаю, что это хорошая идея обновлять БД каждый раз, когда обновляется ваша модель вида нокаута. Может быть, вы должны посмотреть на плагин валидации нокаут. Используя этот плагин, вы можете создать одно и то же пользовательское правило проверки и обновлять базу данных только в случае отправки формы.
О вашей проблеме... Самое простое решение, которое я нашел, - это отправить функцию обратного вызова успешно в расширение проверки как опцию. Как то так
JS:
var ViewModel = function() {
var update = function () {
alert("value was successfully changed");
};
var cancel = function () {
alert("validation failed. previous value was returned");
};
var timeOne = ko.observable("1100").
extend({
acValidTimeHHMM: {
success: update,
fail: cancel
}
});
var timeTwo = ko.observable("1248").
extend({ acValidTimeHHMM: { success: update } });
return {
timeOne: timeOne,
timeTwo: timeTwo
};
};
ko.extenders.acValidTimeHHMM = function(target, option) {
var baseOptions = {
success: null,
fail: null
};
$.extend(baseOptions, option);
var result = ko.computed({
read: target,
write: function (newValue) {
var oldValue = target();
if(newValue == oldValue) return;
var re = /^([0-9]|0[0-9]|1[0-9]|2[0-3])[0-5][0-9]$/;
if (!re.test(newValue)) {
target.notifySubscribers(oldValue);
if(typeof(baseOptions.fail) == "function")
baseOptions.fail();
return;
}
target(newValue);
if(typeof(baseOptions.success) == "function")
baseOptions.success()
}
}).extend({ notify: 'always' });
result(target());
return result;
};
ko.applyBindings(new ViewModel());
HTML:
<p>Time One<input data-bind='value: timeOne' /></p>
<p>Time Two<input data-bind='value: timeTwo' /></p>