knockout.js changing the hasfocus value does not u

2019-07-08 23:58发布

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?

标签: knockout.js
3条回答
2楼-- · 2019-07-09 00:53

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 the hasfocus binding to blur the field, and, because of the bug, updates the value binding too. Because bindings are run in the order listed, the value binding gets updated first, which overwrites the field with the value of title 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/

查看更多
▲ chillily
3楼-- · 2019-07-09 00:59

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:

valueAccessor().call(viewModel)

equals to

viewModel.stopEdit.call(viewModel)

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

viewModel.edit(false);

The issue here is you are mixing up events, see U10's answer for a better approach on tackling this issue.

查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-07-09 01:02

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

查看更多
登录 后发表回答