Knockout observablearray不接受使用服务器值更新的项目

时间:2013-08-26 21:50:56

标签: jquery asp.net-mvc data-binding knockout.js ko.observablearray

我有一个带有敲除绑定的项目列表。简化它看起来像这样:

<ul data-bind="foreach: currentItems ">
    <li>
        <div>
            <span data-bind="text: Heading"></span>
        </div>
   </li>
</ul>

在选择列表中,我有可以添加到第一个列表的潜在项目。双击一个值时,将使用selectedItem启动ajax调用。

<select id="lstSongs" data-bind="options: possibleItems, optionsText: 'Heading', value: selectedItem, dblclick: $root.addItem"></select>

两个数组都使用在服务器上定义的相同模型结构。

viewmodel看起来像这样:

function MyViewModel() {
    var self = this;
    self.currentItems = ko.observableArray([]);
    self.possibleItems = ko.observableArray([]);
    self.selectedItem = ko.observable();

    self.addItem = function(item) {
        $.ajax({
            type: "POST",
            url: "/api/MyController/AddItem",
            contentType: "application/json",
            dataType: "json",
            data: ko.toJSON(item),
            success: function(itemId) {

                // Attempt1
                alert(itemId);
                item.ItemId(itemId);
                alert("hello1");
                alert(item.ItemId);
                currentItems.push(item);

                // Attempt2
                alert(itemId);
                item.ItemId = itemId;
                alert("hello2");
                alert(item.ItemId);
                currentItems.push(item);

                // Attempt3
                alert(itemId);
                selectedItem.ItemId = itemId;
                alert("hello3");
                alert(selectedItem.ItemId);
                currentItems.push(selectedItem);
            }
        });
    };
}

var viewModel = new MyViewModel();
var data = @Html.Raw(new JavaScriptSerializer().Serialize(Model));
ko.mapping.fromJS(data, {}, viewModel);
ko.applyBindings(viewModel);

带有currentItems的列表是使用ko.mapping从MVC初始模型加载的。 possibleItems加载了动态ajax调用的值。但两者都按预期加载,所以我认为那些绑定是可以的。

按预期触发双击。在服务器上检测到呼叫并返回适当的itemId。成功返回后,应在selectedItem上设置该值。然后,应将selectedItem添加到currentItems数组中,并在第一个列表中打开。

我已经进行了多次尝试,但没有成功。当时我和其他人一起试了一次。

Attempt1:返回itemId但未到达第一个hello。为什么?这不是设置可观察属性的方法吗?

尝试2:设置值,显示hello2并报告要设置itemId。但是,push调用不会使该项在currentItem列表中出现。

尝试3:相同的方法,但这次在viewModel selectedItem上设置了属性。这次没有达到hello3。

4 个答案:

答案 0 :(得分:2)

您的第一次尝试不起作用,因为item可能不是作为可观察但是传递的值传递。

您的第二次尝试应该可以正常工作,但您需要使用self变量:

self.currentItems.push(item);

您的第三次尝试与尝试一样的原因不同。

答案 1 :(得分:1)

您必须创建已添加项目的实例,并相应地将其分配给selectedItem和currentItems数组

success: function() {    
    var addedItem = new Item {ItemId:item.ItemId,Heading:item.Heading };
    self.selectedItem(addedItem);
    self.currentItems.push(addedItem);
    alert("Successfully added");   
}

答案 2 :(得分:1)

布拉德利特拉格第一个建议让我走上了正确的道路。为了帮助别人我只需在这里添加工作解决方案:

var addedItem = ko.mapping.fromJSON(ko.toJSON(item));
addedItem.ItemId(itemId);
self.currentItems.push(addedItem);

答案 3 :(得分:0)

我想我可以reproduce你的问题。在我看来,您的问题是您正在对 select 的(双击)进行数据绑定,您希望在 {{1}上触发事件而是。如果您不是option而是alert(itemId),则可以看到这一点:它是传递给您的函数的根视图模型。

我想到了两个解决方案:

  • 使用自定义绑定处理程序查找实际单击的元素(略读类似于this approach);或
  • 删除console.log(item)并使用带有单独模板化项目的列表(&#34;选项&#34;),每个项目都有select绑定。