Как я могу получить нокаут JS для привязки данных на KeyPress вместо потерянного фокуса?
-
10-10-2019 - |
Вопрос
Этот пример нокаут JS Работает так, когда вы редактируете поле и нажмите вкладку, данные ViewModel и, следовательно, текст под полями обновляется.
Как я могу изменить этот код так, чтобы данные ViewModel обновлялись каждый ключ?
<!doctype html>
<html>
<title>knockout js</title>
<head>
<script type="text/javascript" src="js/knockout-1.1.1.debug.js"></script>
<script type="text/javascript">
window.onload= function() {
var viewModel = {
firstName : ko.observable("Jim"),
lastName : ko.observable("Smith")
};
viewModel.fullName = ko.dependentObservable(function () {
return viewModel.firstName() + " " + viewModel.lastName();
});
ko.applyBindings(viewModel);
}
</script>
</head>
<body>
<p>First name: <input data-bind="value: firstName" /></p>
<p>Last name: <input data-bind="value: lastName" /></p>
<h2>Hello, <span data-bind="text: fullName"> </span>!</h2>
</body>
</html>
Решение
<body>
<p>First name: <input data-bind="value: firstName, valueUpdate: 'afterkeydown'" /></p>
<p>Last name: <input data-bind="value: lastName, valueUpdate: 'afterkeydown'" /></p>
<h2>Hello, <span data-bind="text: fullName"> </span>!</h2>
</body>
От документация
Дополнительные параметры
valueUpdate
Если ваша привязка также включает параметр, называемый ValueUpdate, это определяет, какое событие браузера KO должно использовать для обнаружения изменений. Следующие строковые значения являются наиболее часто полезными вариантами:
«Изменить» (по умолчанию) - обновляет модель вашего представления, когда пользователь перемещает фокус на другой элемент управления или в случае элементов, сразу после любого изменения
«KeyUp» - обновляет модель вашего представления, когда пользователь выпускает ключ
«Keypress» - обновляет модель вашего представления, когда пользователь набрал ключ. В отличие от Keyup, это неоднократно обновляется, пока пользователь удерживает ключ.
- «AfterKeyDown» - обновляет модель вашего представления, как только пользователь начнет печатать символ. Это работает, поймав событие браузера Keydown и асинхронно обрабатывая событие.
Из этих вариантов «AfterkeyDown» является лучшим выбором, если вы хотите обновляться модели представления в режиме реального времени.
Другие советы
В Версия 3.2 Вы можете просто использовать TextInput Привязка.:
<input data-bind="textInput: userName" />
Это делает две важные вещи:
- Сделайте немедленные обновления
- Обрабатывает различия в браузерах для выреза, перетаскивания, автозаполнения ...
Таким образом, нет необходимости в дополнительных модулях, пользовательских управлениях и других вещах.
Если вы хотите, чтобы он сделал обновления о afterkeydown
«По умолчанию», вы можете ввести valueUpdate
связывание в value
обработчик связывания. Просто поставьте новый allBindingsAccessor
Чтобы обработчик использовал, который включает afterkeydown
.
(function () {
var valueHandler = ko.bindingHandlers.value;
var getInjectValueUpdate = function (allBindingsAccessor) {
var AFTERKEYDOWN = 'afterkeydown';
return function () {
var allBindings = ko.utils.extend({}, allBindingsAccessor()),
valueUpdate = allBindings.valueUpdate;
if (valueUpdate === undefined) {
return ko.utils.extend(allBindings, { valueUpdate: AFTERKEYDOWN });
} else if (typeof valueUpdate === 'string' && valueUpdate !== AFTERKEYDOWN) {
return ko.utils.extend(allBindings, { valueUpdate: [valueUpdate, AFTERKEYDOWN] });
} else if (typeof valueUpdate === 'array' && ko.utils.arrayIndexOf(valueUpdate, AFTERKEYDOWN) === -1) {
valueUpdate = ko.utils.arrayPushAll([AFTERKEYDOWN], valueUpdate);
return ko.utils.extend(allBindings, {valueUpdate: valueUpdate});
}
return allBindings;
};
};
ko.bindingHandlers.value = {
// only needed for init
'init': function (element, valueAccessor, allBindingsAccessor) {
allBindingsAccessor = getInjectValueUpdate(allBindingsAccessor);
return valueHandler.init(element, valueAccessor, allBindingsAccessor);
},
'update': valueHandler.update
};
} ());
Если вам не удобно «переоценить» value
Привязка, вы можете дать версию пользовательского привязки другого имени и использовать этот обработчик привязки.
ko.bindingHandlers.realtimeValue = { 'init':..., 'update':... };
Подобное решение подойдет для нокаутной версии 2.x. Команда нокаута проделала более полное привязку для текстоподобных входов через ввод текста Переплет в нокаутной версии 3 и выше. Он был разработан для обработки всех методов ввода текста для входов текста и textarea
. Анкет Он даже будет обрабатывать в реальном времени обновление, которое эффективно делает этот подход устаревшим.
Ответ Джеффа Меркадо фантастический, но, к сожалению, сломан нокаутом 3.
Но я нашел ответ, предложенный Do Devs, работая через нокаут 3 изменения. Смотрите нижние комментарии на https://github.com/knockout/knockout/pull/932. Анкет Их код:
//automatically add valueUpdate="afterkeydown" on every value binding
(function () {
var getInjectValueUpdate = function (allBindings) {
return {
has: function (bindingKey) {
return (bindingKey == 'valueUpdate') || allBindings.has(bindingKey);
},
get: function (bindingKey) {
var binding = allBindings.get(bindingKey);
if (bindingKey == 'valueUpdate') {
binding = binding ? [].concat(binding, 'afterkeydown') : 'afterkeydown';
}
return binding;
}
};
};
var valueInitHandler = ko.bindingHandlers.value.init;
ko.bindingHandlers.value.init = function (element, valueAccessor, allBindings, viewModel, bindingContext) {
return valueInitHandler(element, valueAccessor, getInjectValueUpdate(allBindings), viewModel, bindingContext);
};
}());
http://jsfiddle.net/mbest/gkjnt/
Редактировать KO 3.2.0 теперь имеет более полное решение с новой привязкой «TextInput». См. Ответ Сальвидордали