动态添加新行时,knockout data-bind值不正确

时间:2017-01-10 14:59:40

标签: knockout.js

我的节目:

我有一个数据表,它是一个可观察的可观察数组。

  • 当从最后一行的最后一个输入中跳出时,它会添加一行新的空输入。焦点在新行的第一个输入中设置。
  • 项目编号中的用户类型;当他们选中时,它会对该项目编号进行一些检查,并根据它是否通过这些检查
    1. 继续下一个字段
    2. 它返回到该输入并给出一条消息,指出无效输入并选择文本。

一切正常。因此,用户通过并输入该行中的所有有效数据,然后从最后一个输入中选中,并添加一个新行。 但是它没有将焦点设置为第一个输入,我甚至无法点击那里,我假设因为hasFocus / invalidItem变量设置为false。我不确定在添加新行时如何将其设置为true。

以下是我的相关HTML:

<tbody data-bind="foreach: items">        
        <tr>
            <td>
                <div data-bind="if: (itemNo.length < 1)"><input data-bind="value: itemNo, hasFocus: $parent.invalidItem, selected: $parent.invalidItem, event: { blur: $parent.checkItemNo }, attr: { name: 'brochureitems[' + $index() + '].itemNo', id: 'brochureItems_' + $index() + '__itemNo' }, validationOptions: { errorElementClass: 'input-validation-error' }" class="form-control item-id" /></div>

这是我的相关淘汰赛:

var itemModel = function (data) {
        var self = this;
        self.itemNo = ko.observable(data ? data.itemNo : undefined).extend( {
            required: {
                params: true,
                message: "Item no. required."
            }
        });
        self.brocCode = ko.observable(data ? data.brocCode : undefined).extend( {
            required: {
                params: true,
                message: "Bro code required."
            }
        });
        self.itemDesc = ko.observable(data ? data.itemDesc : undefined).extend( {
            required: {
                params: true,
                message: "Item desc required."
            }
        });
        self.retail = ko.observable(data ? data.retail : undefined).extend( {
            required: {
                params: true,
                message: "Retail required."
            }
        });
        self.prizeNum = ko.observable(data ? data.prizeNum : undefined).extend( {
            required: {
                params: true,
                message: "Prize num required."
            }
        });
        self.itemOrder = ko.observable(data ? data.itemOrder : undefined).extend( {
            required: {
                params: true,
                message: "Item order required."
            }
        });
    }
var itemsModel = function(items) {
        var self = this;
        self.items = ko.observableArray(items);

        self.invalidItem = ko.observable(true);
        console.log("focus has been set");

        self.checkItemNo = function(data) {
            console.log("lost focus - " + self.invalidItem());
            var itemNo = $.trim(data.itemNo());

            if (itemNo != "") {
                var item = "";
                $.each(window.listOfItems, function(i, v) {
                    if (v.No.search(itemNo) != -1) {
                        item = v.Description;
                        return;
                    }
                });
                if(item != "") {
                    var match = ko.utils.arrayFirst(self.items(), function(newItem) {
                        return itemNo === newItem.itemNo;
                    });
                    console.log("match: " + match);
                    if (!match) {
                        data.itemDesc(item);
                    } else { // item already entered
                        setTimeout(function() { self.invalidItem(true); }, 1);
                        slideDownMsg("Item already entered.");
                        slideUpMsg(3000);
                    }
                } else { // invalid item #
                    setTimeout(function() { self.invalidItem(true); }, 1);
                    slideDownMsg("Invalid item number.");
                    slideUpMsg(3000);
                }
            }
        }        

        self.submit = function() {
            //self.showErrors(true);
            if (viewModel.errors().length === 0) {
                console.log('Thank you.');
                $("#brochureForm").submit();
            }
            else {
                console.log('Please check your submission.');
                viewModel.errors.showAllMessages();
                $(".input-validation-error").first().focus();
            }
        }

        self.addLine = function() {
            self.invalidItem(true);
            console.log(self.invalidItem());
            self.items.push( new itemModel() );
            //setTimeout(function() { self.invalidItem(true); }, 1);
        };

更新

好吧,我现在就像我的本地代码一样工作。在这里小提琴:https://jsfiddle.net/tLfezuu1/8/ 因此,当用户选中最后一个输入时,它会添加一行新的空白输入。用户在第一个输入和点击选项卡中键入数字。它对该号码运行一些检查,如果检查通过则将焦点发送到下一个输入,或者如果检查失败则将焦点发送回该输入,突出显示文本。

1 个答案:

答案 0 :(得分:0)

itemNo是一个可观察的,所以你不能在不使用()的情况下阅读它,除非你将observable直接传递给一个解包它的绑定。由于您未初始化itemNo,因此它始于undefined,无论如何您都无法读取其长度。由于undefined和空字符串都是假的,因此您可以将ifnotif与observable一起使用。

<div data-bind="ifnot: itemNo">...</div>
<div data-bind="if: itemNo">...</div>

https://jsfiddle.net/rwa03vrb/15/