I have http://jsfiddle.net/ksCSn/1/
HTML
<input type="text" data-bind="
value: title,
hasfocus: edit,
onEnter: stopEdit" />
<p data-bind="text: title"></p>
JS
ko.bindingHandlers.onEnter = {
init: function(element, valueAccessor, _, viewModel) {
ko.utils.registerEventHandler(element, 'keydown', function(evt) {
if (evt.keyCode === 13)
valueAccessor().call(viewModel);
});
}
}
function ViewModel() {
this.title = ko.observable("default value");
this.edit = ko.observable(false);
this.stopEdit = function() {
this.edit(false);
// If the edit update is in a timeout, then it works
// var edit = this.edit;
// setTimeout(function() { edit(false); }, 0);
};
}
ko.applyBindings(new ViewModel());
How come when the Enter key is pressed while editing in the input field, the value does not update?
And if I change the edit update so that it is queued up as a timeout, then it works. Why is that?
This is because of a "bug" in Knockout (see https://github.com/SteveSanderson/knockout/issues/321) that causes all bindings to update together. When you change your
edit
property, it updates thehasfocus
binding to blur the field, and, because of the bug, updates thevalue
binding too. Because bindings are run in the order listed, thevalue
binding gets updated first, which overwrites the field with the value oftitle
in the view model.A simple change that fixes this is to re-order the bindings so that
hasfocus
will run first: http://jsfiddle.net/mbest/ksCSn/8/ValueAccessor is a function that will evaluate either to a plain property or a ko.observable, depending on what you passed to the binding.
In your example you are passing the stopEdit function, hence:
equals to
Passing viewModel to the function will reset the scope from this to your viewModel. In your example this will efectively set the edit property of your viewModel to false, thus You could also write this as
The issue here is you are mixing up events, see U10's answer for a better approach on tackling this issue.
You should use Blur when pressing enter, I've adjusted your JS Fiddle
But m.b you should try to use another event to update value instead of pressing enter for changing value? For example afterkeydown: Js Fiddle
Also see KnockoutJS documentation