在挖空中动态添加焦点输入到observableArray

时间:2013-10-23 07:04:30

标签: javascript knockout.js focus

在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

几乎有效。

我在行创建方面取得了成功 - 这是我的生活部分,但对于我的生活,我无法在创建的原始数据中进行第一次输入。

任何想法(我经历了大量的建议,其中没有一个在上述环境中有效)?

2 个答案:

答案 0 :(得分:0)

我可能会忽略这一点,但为什么不将你的hasFocus设置为编辑()而不是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

答案 1 :(得分:0)

通常需要避免将jQuery与Knockout混合使用。对于大多数情况,Knockout也有选择。在您的情况下,要查看的内容为the event bindingthe hasFocus binding

查看代码,我将View更新为:

<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>

顺便说一句,如果您在用户按Tab键时创建新行的“MS Word Style”后,您还可以绑定到“keypress”事件并检查正确的键码(对于制表符)。

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

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

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中查看所有这些内容。