【问题标题】:Focus input added dynamically to observableArray in knockout在淘汰赛中将焦点输入动态添加到 observableArray
【发布时间】:2013-11-01 08:01:22
【问题描述】:

在 KO 3.0.0.beta 中(我几乎可以肯定它在 2.3 中是一样的)我正在尝试将新行添加到动态创建的表中:

HTML

<div id="root">
    <table>
        <tbody data-bind="foreach: events">
            <tr>
                <td>
                    <input type="text" data-type="name" data-bind="value: name, css: {hidden: !editing()}, hasFocus: true">
                </td>
                <td>
                    <input type="text" data-type="method" data-bind="value: age, css: {hidden: !editing()}">
                </td>
            </tr>
        </tbody>
    </table>
</div>

JavaScript

var $root = $('#root');

$root.on('blur', 'table input', function(event) {
    var data = ko.dataFor(event.target), 
        context = ko.contextFor(event.target),
        $input = $(event.target), 
        newData;

    data.editing(false);

    if($input.closest('td').is(':last-child') && $input.closest('tr').is(':last-child')) {
        newData = {
            name: '', 
            age: '', 
            editing: ko.observable(false)
        };

        context.$root.events.push(newData);
        newData.editing(true);  
    }
});

var data = {                
    events: [
        {name: 'aaa', age: '22', editing: false},
        {name: 'bbb', age: '33', editing: false},
        {name: 'ccc', age: '44', editing: false}
    ]
};

var mapping = {
    events: {
        key: function(data) {
            return ko.unwrap(data.name);
        }
    }
};

var observable = ko.mapping.fromJS(data, mapping);

ko.applyBindings(observable, $root[0]);

JSFiddle

几乎有效。

我在行创建方面很成功 - 这是最简单的部分,但在我的一生中,我无法使创建的原始数据中的第一个输入成为焦点。

有什么想法(我提出了很多建议,但在上述设置中没有一个可行)?

【问题讨论】:

  • 你在混合 jQuery 和 KO,它注定要失败。添加一个可观察的 isFocused,将其绑定到 hasFocus 绑定
  • 第二个@Anders。你应该把它变成一个答案。它可能不是 OP 所追求的,但它是实际问题的最干净的解决方案,此外:其他人可能会发现它也有帮助。
  • @Anders jquery 用于事件绑定。完全正交。我愿意接受建议,所以请务必将此作为答案。我尝试使用 isFocused。无法让它工作。

标签: javascript knockout.js focus


【解决方案1】:

我可能没有抓住重点,但为什么不将你的 hasFocus 设置为 editing() 而不是 true?

<div id="root">
    <table>
        <tbody data-bind="foreach: events">
            <tr>
                <td>
                    <input type="text" data-type="name" data-bind="value: name, css: {hidden: !editing()}, hasFocus: editing()">
                </td>
                <td>
                    <input type="text" data-type="method" data-bind="value: age, css: {hidden: !editing()}">
                </td>
            </tr>
        </tbody>
    </table>
</div>

小提琴here

【讨论】:

  • 你试过你自己的小提琴吗?它不起作用。不过感谢您的回复。
  • 我一定是误会了......那它应该如何工作?
  • 添加的新行应该关注第一个输入字段 - 以便用户可以在按下前一行的“tab”后立即输入。
【解决方案2】:

避免像这样将 jQuery 与 Knockout 混合使用通常是值得的。在大多数情况下,Knockout 也有选项。在您的情况下,要查看的是 the event bindingthe hasFocus binding

查看您的代码,我会将视图更新为如下内容:

<tr>
    <td>
        <input type="text" data-bind="value: name, 
                                      hasFocus: editingName">
    </td>
    <td>
        <input type="text" data-bind="value: age, 
                                      hasFocus: editingAge, 
                                      event: { blur: $root.onBlurAgeEdit }">
    </td>
</tr>

顺便说一句,如果您在用户按下选项卡时在“MS Word 样式”创建新行之后,您还可以绑定到“keypress”事件并检查正确的键码(用于选项卡)。

请注意,我已将 editing 可观察对象分成两个可观察对象:editingNameeditingAge

只要年龄input 模糊,函数onBlurAgeEdit 就会触发。它看起来像这样:

self.onBlurAgeEdit = function (item) {
    // Unwrap the array
    var myEvents = self.events();

    // Check if this function was called for the *last* item in the array
    if (myEvents[myEvents.length-1] === item) {

        // Make sure the last item isn't in edit mode anymore
        item.editingAge(false);

        // Push a new item that has *name* in edit mode
        self.events.push({name: ko.observable(''),
                          age: ko.observable(''),
                          editingName: ko.observable(true),
                          editingAge: ko.observable(false)});
    }
};

请注意,对于 Firefox you'll need to throttle,可观察对象使 hasFocus 绑定发挥得很好。

this fiddle 中查看所有这些工作。

【讨论】:

  • 我的解释一定很糟糕。你的完全和我原来的一样。这并不好。在最后一个可见输入上按 Tab 后 - 应该添加一个新行,并且该行中的第一个输入应该 聚焦 并准备好输入。另外,你可以看到我在上面的代码中使用了hasFocus
  • 正确的行为确实发生在我的 IE10 中。令我惊讶的是,Webkit 无法工作until I let bits of the onBlur function run on its own thread。不过,我没有时间让它在 Firefox 上运行,直接向上油门扩展似乎不起作用。有关更多信息,您可能需要点击上述链接并进行更多调查。
猜你喜欢
  • 1970-01-01
  • 2013-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-16
  • 1970-01-01
相关资源
最近更新 更多