1

我正在尝试为我的 observableArray 的元素设置一个值,并得到一个我无法解决的错误:

Uncaught TypeError: Property 'Locked' of object #<Object> is not a function 

这是我写的一段代码:

$(function () {
    // -----------------------------------------------------------------------//
    // ** brand - model ** //
    // -----------------------------------------------------------------------//
    var Brand = function (e) {
        var self = this;
        self.Id = ko.observable(e ? e.Id : '');
        self.Name = ko.observable(e ? e.Name : '').extend({ required: true });
        self.Description = ko.observable(e ? e.Description : '');
        self.LogoId = ko.observable(e ? e.LogoId : '');
        self.Logo = (e ? (e.LogoId != null ? ko.observable(new Logo(e.Logo)) : null) : null);
        self.DisplayOrder = ko.observable(e ? e.DisplayOrder : '');
        self.Deleted = ko.observable(e ? e.Deleted : '');
        self.State = ko.observable(e ? e.State : '');
        self.DateChanged = ko.observable(e ? e.DateChanged : '');
        self.DateCreated = ko.observable(e ? e.DateCreated : '');
        self.Locked = ko.observable(e ? e.Locked : '');

        // validation
        self.Errors = ko.validation.group(self);
        self.IsValid = function () {
            if (self.Errors().length > 0) {
                self.Errors.ShowAllMessages();
                return false;
            }
            return true;
        };
    };


    // -----------------------------------------------------------------------//
    // ** logo - model ** //
    // -----------------------------------------------------------------------//
    var Logo = function (e) {
        var self = this;
        self.Id = ko.observable(e ? e.Id : '');
        self.FileName = ko.observable(e ? e.FileName : '');
        self.URL = ko.observable(e ? e.URL : '');
        self.PictureType = ko.observable(e ? e.PictureType : '');
        self.Deleted = ko.observable(e ? e.Deleted : '');
        self.State = ko.observable(e ? e.State : '');
        self.DateChanged = ko.observable(e ? e.DateChanged : '');
        self.DateCreated = ko.observable(e ? e.DateCreated : '');
    };


    // -----------------------------------------------------------------------//
    // ** view - model ** //
    // -----------------------------------------------------------------------//
    var BrandViewModel = function (hub) {
        // init
        var self = this;
        var url = "/api/brand/brands";

        // public data properties
        self.Brands = ko.observableArray([]);
        self.NewBrand = ko.observable(new Brand());

        // -----------------------------------------------------------------------//
        // ** Web API Actions ** //
        // -----------------------------------------------------------------------//

        // load
        self.Load = function () {
            // block
            self.BlockBrands();

            // Initialize the view-model
            $.ajax({
                url: url,
                type: 'GET',
                contentType: 'application/json; charset=utf-8',
                success: function (data) {
                    // add brands
                    self.Brands(data);

                    // tooltip
                    self.InitTooltip();
                },
                error: function (err) {
                    self.ShowError(err);
                },
                complete: function () {
                    self.UnblockBrands();
                }
            });
        }


        // -----------------------------------------------------------------------//
        // ** SignalR Actions ** //
        // -----------------------------------------------------------------------//

        self.LockItem = function (id) {
            // find item
            var brand = self.getBrandById(id);
            brand.Locked(true);
        }

        self.UnlockItem = function (id) {
            // find item
            var brand = self.getBrandById(id);
            brand.Locked(false);
        }

        // -----------------------------------------------------------------------//
        // ** Utilities ** //
        // -----------------------------------------------------------------------//

        self.getBrandById = function (Id) {
            return ko.utils.arrayFirst(self.Brands(), function (item) {
                if (item.Id == Id) {
                    return item;
                }
            });
        }



        self.Load();
    };

    // -----------------------------------------------------------------------//
    // ** init ** //
    // -----------------------------------------------------------------------//
    var hub = $.connection.brand;
    var brandViewModel = new BrandViewModel(hub);

    // -----------------------------------------------------------------------//
    // ** signalR ** //
    // -----------------------------------------------------------------------//


    hub.client.LockItem = function (id) {
        brandViewModel.LockItem(id);
    }

    hub.client.UnlockItem = function (id) {
        brandViewModel.UnlockItem(id);
    }

    $.connection.hub.start();

    // -----------------------------------------------------------------------//
    // ** knockout ** //
    // -----------------------------------------------------------------------//

    // knockout validation
    ko.validation.configure({
        insertMessages: true,
        decorateElement: true,
        errorElementClass: 'error'
    });

    // knockout binding
    ko.applyBindings(brandViewModel);

});

HTML - 淘汰赛绑定

<table data-bind="visible: Brands().length > 0" class="table table-striped table-bordered table-hover" id="brands">       
    <tbody data-bind="foreach: Brands">
        <tr>
            <td class="align-center">
                <!-- ko if: Logo -->
                <img data-bind="attr: { src: Logo.URL() + '?width=50&height=50' }" class="img-polaroid" />
                <!-- /ko -->
            </td>
            <td data-bind="text: Name()"></td>
            <td data-bind="date: DateChanged()" class="align-center"></td>
            <td class="align-center">
                <!-- ko ifnot: Locked -->
                <a data-bind="click: $root.Edit" class="btn blue tip" data-original-title="wijzigen"><i class="icon-edit"></i></a>
                <a data-bind="click: $root.ShowDeleteModal" class="btn red tip" data-original-title="verwijderen"><i class="icon-trash"></i></a>
                <!-- /ko -->
                <!-- ko if: Locked -->
                <div class="btn black"><i class="icon-lock"></i></div>
                <!-- /ko -->
            </td>
        </tr>
    </tbody>
</table>

我在分配值时做错了什么?我也试过这样做:brand.Locked = true; . 这次我没有收到任何错误,但淘汰赛没有响应。

4

1 回答 1

0

问题是,当您调用时ko.utils.arrayFirst(self.Brands()),您Brands不再是observables普通的 javascript objects'Locked'作为属性而不是observable函数),这是因为当您从服务器检索数据并将其推送到您的Brands数组时,你没有用ko.observableArray.

尝试:

success: function (data) {
              // add brands
              self.Brands(ko.observableArray(data));

在你的getBrandById功能中:

self.getBrandById = function (Id) {
            return ko.utils.arrayFirst(self.Brands(), function (item) {
                if (item.Id() == Id) {
                    return item;
                }
            });

编辑:

实际上,由于您的Brands数组包含Brand对象,ko.observableArray因此不足以将每个对象的内部属性也转换Brandobversable。您将需要使用该mapping插件,如下所示:

success: function (data) {
             // add brands
             self.Brands = ko.mapping.fromJS(data);

更多关于 ko.utils.mapping 插件的信息在这里

于 2013-07-05T06:52:32.453 回答