Knockout textInput在模板内失去焦点

时间:2015-05-26 14:24:14

标签: javascript knockout.js

(这是this question

的后续行动

在Knockout.js中,textInput绑定在每次击键后更新模型,并允许我实现一个简单的输入掩码。它本身很好用,但是当输入字段在模板中时,每次击键后该字段都会失去焦点。

这个小提琴演示了这个问题。请注意,我需要一些$ parent trickery来使输入字段在两个方向上工作(读取和写入)。如果我使用$ data,它会在外部更新时读取新值,但不会将其写入模型并且不应用输入掩码。

https://jsfiddle.net/h0qh3ecc/4/

简化代码如下:

HTML:

textInput (this one works):<br>
<input data-bind="textInput: formattedString" >
<div data-bind="text: formattedString"></div>
<hr>
template textInput ($parent loses focus / $data doesn't call write):<br>
<script type="text/html" id="input-standalone-template">
    <input data-bind="textInput: $parent.formattedString"> <input data-bind="textInput: $data">
</script>
<div data-bind="template: { name: 'input-standalone-template', data: formattedString }"></div>
<hr>

JavaScript的:

var model = (function () {
    function format(str) {
        var undone = str.replace(/-/g, '');
        if (undone.length > 3) {
            undone = undone.substr(0,3) + '-' + undone.substr(3);
        }
        return undone;
    }

    var displayString = ko.observable('');
    var formattedString = ko.computed({
        read: function () {
            return displayString();
        },
        write: function (newValue) {
            var f = format(newValue);
            console.debug("Format", newValue, "=", f);
            displayString(f);
        }
    });

    return {
        formattedString: formattedString
    };
}());
ko.applyBindings(model)

这是一个错误吗?有解决方法吗?

1 个答案:

答案 0 :(得分:0)

我刚刚找到了一种解决方法:我必须将$data(或$parent,具体取决于页面结构)而不是字段直接传递给模板data参数。必须相应地调整模板。

例如,而不是

<!-- define template -->
<script type="text/html" id="my-input-template">
    <input data-bind="textInput: $data">
</script>

<!-- call template (passing field, causes focus issues) -->
<div data-bind="template: {
                    name: 'my-input-template',
                    data: formattedString
                }">
</div>

我应该做

<!-- define template -->
<script type="text/html" id="my-input-template">
    <input data-bind="textInput: formattedString">
</script>

<!-- call template (passing $data, works fine) -->
<div data-bind="template: {
                    name: 'my-input-template',
                    data: $data
                }">
</div>

由于某些不明原因,此更改解决了问题。