当我向数组添加新项目时,KnockoutJS数据消失

时间:2013-05-13 21:42:09

标签: javascript knockout.js

在jsfiddle上查看问题:http://jsfiddle.net/6bFsY/3/

当您单击“添加用户”然后再次单击“添加用户”时,扩展名下拉字段中的所有数据都将消失。这是在我添加电子邮件列后发生的。 电子邮件字段预先填充了扩展名下拉列表中选择的任何内容(电子邮件是其对象的一部分)。

此外,扩展下拉列表每行唯一,脚本的一部分告诉它如果它存在于前一行,则将其从数组中删除。

JS

window.usrViewModel = new function () {

    var self = this;
    window.viewModel = self;

    self.list = ko.observableArray();
    self.pageSize = ko.observable(10);
    self.pageIndex = ko.observable(0);
    self.selectedItem = ko.observable();
    self.extData = ko.observableArray();
    self.validAccess = [{
        'name': 'No Access',
        'id': 'none'
    }, {
        'name': 'System Settings',
        'id': 'pbx'
    }, {
        'name': 'Accounting',
        'id': 'billing'
    }, {
        'name': 'Full Administrator',
        'id': 'full'
    }];
    self.availableExtData = ko.computed(function () {

        var inUse = [];
        if (!self.selectedItem()) return inUse;
        ko.utils.arrayForEach(self.list(), function (item) {
            if (inUse.indexOf(item.usrExtVal().extension) == -1 && self.selectedItem() != item) inUse.push(item.usrExtVal().extension);
            self.selectedItem().usrEmail(self.selectedItem().usrExtVal().email);
        });

        return ko.utils.arrayFilter(self.extData(), function (item) {
            return inUse.indexOf(item.extension) == -1;
        });

    });

    self.edit = function (item) {
            if (self.selectedItem()) self.save();
            self.selectedItem(item);
    };

    self.cancel = function () {
        self.selectedItem(null);
    };

    self.add = function () {
            if (self.selectedItem()) self.save();

            var newItem = new Users();
            self.selectedItem(newItem);
            self.list.push(newItem);
            self.moveToPage(self.maxPageIndex());
    };
    self.remove = function (item) {

        if (confirm('Are you sure you wish to delete this item?')) {

            self.list.remove(item);
            if (self.pageIndex() > self.maxPageIndex()) {
                self.moveToPage(self.maxPageIndex());
            }

        }
        $('.error').hide();

    };
    self.save = function () {
            self.selectedItem(null);
    };

    self.templateToUse = function (item) {
        return self.selectedItem() === item ? 'editUsrs' : 'usrItems';
    };

    self.pagedList = ko.dependentObservable(function () {
        var size = self.pageSize();
        var start = self.pageIndex() * size;
        return self.list.slice(start, start + size);
    });
    self.maxPageIndex = ko.dependentObservable(function () {
        return Math.ceil(self.list().length / self.pageSize()) - 1;
    });
    self.previousPage = function () {
        if (self.pageIndex() > 0) {
            self.pageIndex(self.pageIndex() - 1);
        }
    };
    self.nextPage = function () {
        if (self.pageIndex() < self.maxPageIndex()) {
            self.pageIndex(self.pageIndex() + 1);
        }
    };
    self.allPages = ko.dependentObservable(function () {
        var pages = [];
        for (i = 0; i <= self.maxPageIndex(); i++) {
            pages.push({
                pageNumber: (i + 1)
            });
        }
        return pages;
    });
    self.moveToPage = function (index) {
        self.pageIndex(index);
    };

};

ko.applyBindings(usrViewModel, document.getElementById('usrForm'));

function Users(fname, lname, email, phone, access, usrExtVal, usrEmail) {
    this.fname = ko.observable(fname);
    this.lname = ko.observable(lname);
    this.email = ko.observable(email);
    this.phone = ko.observable(phone);
    this.access = ko.observable(access);
    this.usrExtVal = ko.observable(usrExtVal);
    this.usrEmail = ko.observable(usrEmail);
}
var ajaxResultExt = [{
    'extension': '123',
    'name': 'Stephen',
    'email': 'test@test.com'
}, {
    'extension': '123',
    'name': 'Stephen',
    'email': 'stephen@test.com'
}];

usrViewModel.extData(ajaxResultExt);

HTML

                    <fieldset title="Users">
                        <legend>2</legend>
                        <div>
                            <div class="cbp-content">
                                <form id="usrForm">
                                <h2>Users</h2>
                                <table class="table table-striped table-bordered" data-bind='visible: pagedList().length > 0'>
                                    <thead>
                                        <tr>
                                            <th>First Name</th>
                                            <th>Last Name</th>
                                            <th>Phone Number</th>
                                            <th>Access</th>
                                            <th>Extension</th>
                                            <th>Email</th>
                                            <th style="width: 100px; text-align:right;" />
                                        </tr>
                                    </thead>
                                   <tbody data-bind=" template:{name:templateToUse, foreach: pagedList }"></tbody>
                                </table>
                                <!-- ko if: 2 > pagedList().length -->
                                <p class="pull-right"><a class="btn btn-primary" data-bind="click: $root.add" href="#" title="edit"><i class="icon-plus"></i> Add Users</a></p>
                                <!-- /ko -->
                                <div class="supOneUsr" style="display:none;"><i class="icon-warning-sign"></i> <span style="color:red;">Please supply at least 1 User with Administrator Rights</span></div>
                                <div class="pagination pull-left" data-bind='visible: pagedList().length > 0'>
                                    <ul><li data-bind="css: { disabled: pageIndex() === 0 }"><a href="#" data-bind="click: previousPage">Previous</a></li></ul>
                                    <ul data-bind="foreach: allPages">
                                        <li data-bind="css: { active: $data.pageNumber === ($root.pageIndex() + 1) }"><a href="#" data-bind="text: $data.pageNumber, click: function() { $root.moveToPage($data.pageNumber-1); }"></a></li>
                                    </ul>
                                    <ul><li data-bind="css: { disabled: pageIndex() === maxPageIndex() }"><a href="#" data-bind="click: nextPage">Next</a></li></ul>
                                </div>

                                <br clear="all" />
                                    <script id="usrItems" type="text/html">
                                   <tr>
                                        <td data-bind="text: fname"></td>
                                        <td data-bind="text: lname"></td>
                                        <td data-bind="text: phone"></td>
                                        <td data-bind="text: access.asObject && access.asObject() && access.asObject().name"></td>
                                        <td data-bind="text: usrExtVal().extension"></td>
                                        <td data-bind="text: usrEmail"></td>
                                        <td class="buttons">
                                            <a class="btn" data-bind="click: $root.edit" href="#" title="edit"><i class="icon-edit"></i></a>
                                            <a class="btn" data-bind="click: $root.remove" href="#" title="remove"><i class="icon-remove"></i></a>
                                        </td>
                                    </tr>
                                </script>
                                 <script id="editUsrs" type="text/html">
                                   <tr>
                                        <td><input data-errorposition="b" class="required" name="fname" data-bind="value: fname" /></td>
                                        <td><input data-errorposition="b" class="required" name="lname" data-bind="value: lname" /></td>
                                        <td><input data-errorposition="b" class="required" name="phone" data-bind="value: phone" /></td>
                                        <td><select class="accessSelect" data-bind="options: $root.validAccess, optionsText: 'name', optionsValue: 'id', value: access, valueAsObject: 'asObject'"></select></td>
                                        <td><select id="extData" data-bind="options: $root.availableExtData, optionsText: 'extension', value: usrExtVal"></select></td>
                                        <td><input id="extEmail" data-errorposition="b" class="required" name="email" data-bind="value: usrEmail" /></td>
                                        <td class="buttons">
                                            <a class="btn btn-success" data-bind="click: $root.save" href="#" title="save"><i class="icon-ok"></i></a>
                                            <a class="btn" data-bind="click: $root.remove" href="#" title="remove"><i class="icon-remove"></i></a>
                                        </td>
                                   </tr>
                                </script>
                                </form>

                            </div>
                        </div>
                    </fieldset>

1 个答案:

答案 0 :(得分:2)

您的代码中存在一些问题。

  1. availableExtData尝试访问usrExtVal的子属性,有时为undefined。该访问会导致错误,从而阻止进一步执行计算。因此,您需要先检查是否设置了usrExtVal

  2. ajaxResultExt中有两个条目,但它们都具有相同的扩展名。因此,一旦您为第一个项目选择了123,则第二个项目没有任何剩余,因为两个123值都将被删除。因此,您的扩展程序必须是唯一的。

  3. 您正在usrEmail的循环内更新availableExtData,这没有任何意义。它应该在单独的ko.computed

  4. 以下是您使用这些修补程序的示例:http://jsfiddle.net/mbest/6bFsY/5/