【问题标题】:Editing existing viewmodel data编辑现有视图模型数据
【发布时间】:2013-09-13 11:08:56
【问题描述】:

我已经搜索了几天的答案,但似乎找不到适合我的答案,所以如果在其他地方得到回答,我深表歉意。

我有一个

viewModel = ko.mapping.fromJS(@Html.Raw(JsonConvert.SerializeObject(Model))); 

具有基本结构

区域 = ID:{} 大小:{} 详细信息:{[ 州:{} 邮政编码:{[邮政编码:{44444},邮政编码:{11111},{..}]}]}

function ZoneDetail() {
    var self = this;
    self.ZoneId = ko.observable();
    self.Zipcodes = ko.observableArray();

    self.addZipcode = function () {
        self.Zipcodes.push(new Zipcode());
    };

    self.deleteZipcode = function (zip) {
        self.Zipcodes.remove(zip);
    };

};

现在我的问题在于尝试编辑预先存在的数据。

上面的代码在制作新的细节并将新的邮政编码列表添加到这些新细节时非常有效。但是,如果我想删除邮政编码 44444 或将另一个邮政编码添加到详细信息 44444 中,它就不会做任何事情而没有错误。

<input type="button" value="Add Zipcode" data-bind="click: $data.addZipcode"  style="font-size: .9em;" />

<a href='#' data-bind="click: $parent.deleteZipcode">Delete</a>

这些是我对按钮的绑定,它们非常适合新的东西,但在编辑传入的现有数据时什么也不做也不会出错

【问题讨论】:

    标签: c# javascript jquery asp.net-mvc-4 knockout.js


    【解决方案1】:

    你在这里有一部未完成的交响乐。 .addZipcode 非常简单,因为您只需在某处输入一个输入并将其添加到您的 Zipcode 数组中。要删除,您需要一种方法来识别要删除的邮政编码。我会提供一个当前邮政编码的下拉列表,如下所示:

    <select data-bind="options: $root.Zipcodes, optionsText: 'value', value: $root.selectedZipcode, optionsCaption: 'Choose...'"></select><br />
    <button data-bind="click: $root.deleteZipcode">Delete Selected Zipcode</button>
    

    为此,您的邮政编码必须具有以下数据结构:

    var zipcode = { value: 44444 };
    

    您当前的邮政编码数组对我来说没有意义。它们是对象,但 Zipcode 本身的值未设置为任何属性名称。结构应该是:

    Zipcodes: [{ Zipcode: 44444 }, { Zipcode: 11111 }, {...}]
    

    我假设它会是这样,所以相应地替换:

    Zipcodes: [{ value: 44444 }, { value: 11111 }, {...}]
    

    您需要做的另一件事是将 selectedZipcode 属性添加到您的 ViewModel:

    function ZoneDetail () {
        ...
        self.selectedZipcode = ko.observable();
        ...
        self.deleteZipcode = function () {
            if (self.selectedZipcode()) {
                ko.utils.arrayRemoveItem(self.Zipcodes(), selectedZipcode());
                self.selectedZipcode(null);
            }
        };
    }
    

    *注意:我不喜欢进行函数调用或在数据绑定中使用逻辑。对我来说,在数据绑定的函数引用中预期的唯一可接受的参数是当前上下文。我的意思是:

    function ViewModel() {
        var self = this;
        self.Zipcodes = ko.observableArray([{ value: 44444 }, { value: 11111 }]);
        self.deleteZipcode = function (Zipcode) {
            ko.utils.arrayRemoveItem(self.Zipcodes(), Zipcode());
        };
    }
    

    还有 ViewModel:

    <div data-bind="foreach: $root.Zipcodes">
        <!-- The $data context in this div is each individual Zipcode item.  Any function references in here will be passed the current data context when called -->
        <span data-bind="text: $data.value"></span><br />
        <button data-bind="click: $root.deleteZipcode">Delete This Zipcode</button>
    </div>
    

    如果你愿意,你可以这样做,不同的是每个 Zipcode 对象列表都有自己的删除按钮,也许你只想要一个按钮。所以这更值得深思。

    【讨论】:

    • 对不起我蹩脚的伪代码,我认为这里最重要的是 $root.Zipcodes 和 arrayremoveItem。另外,我不能使用下拉列表,因为需要同时显示所有邮政编码,并且每个邮政编码都必须有自己的“删除”按钮,因此 Delete 实际上位于其对应的邮政编码旁边,因此删除按钮与邮政编码的比例为 1-1
    • 啊,好的。然后你会按照我的问题中&lt;hr /&gt; 之后的第二个示例(在 *Note 之后),如下所示:jsFiddle
    • 你还是不行。我真的认为我的问题更多在于来自 ko.mapping.fromJS(); 的 Zipcodes 数组;它就像从那里传递到视图模型的数组是不可编辑或不可观察的。
    • 如果您问题中的示例数据结构是输出的内容,那么这就是您的问题所在。请注意,您的所有属性都是对象。 ko.mapping.fromJS() 将使它们成为所有可观察值,包括 Zipcodes 数组(它包含在 {} 中)。这就是您要从中映射的内容:Zipcodes:{[Zipcode: {44444}, Zipcode: {11111},{..}]}。想象一下,var foo = {44444}; 这不是一个有效的对象声明。
    【解决方案2】:

    deleteZipCode 方法需要一个参数:

    self.deleteZipcode = function (zip)
    

    您没有在点击时将 zip 传递给函数。试试

    <a href='#' data-bind="click: $parent.deleteZipcode(44444)">Delete</a>
    

    或将 44444 替换为您要删除的值。

    【讨论】:

    • 结果行为不是您所期望的。 exampledeleteItem函数在页面绑定过程中被解析,返回值null是点击按钮时点击绑定调用的值,所以什么也没有发生。奇怪的是,addItem 按钮会导致调用deleteItem 函数,因为它会向foo 数组添加一个项目,从而导致KO 更新DOM。所以在绑定中调用函数时要小心。我个人认为应该完全避免。
    猜你喜欢
    • 1970-01-01
    • 2011-10-24
    • 1970-01-01
    • 2012-01-28
    • 1970-01-01
    • 2020-12-25
    • 2020-04-13
    • 2017-01-09
    • 1970-01-01
    相关资源
    最近更新 更多