Knockout Nested Computed Property在页面加载时绑定,但在Parent Computed Property更新后失败

时间:2014-06-13 15:59:51

标签: knockout.js

我正在尝试创建一个菜单,当您单击代表其中一个组的按钮时,会出现一个图像,显示最受欢迎的产品。我知道这可以更简单,但我正在尝试使用现有的数据模型。

我正在尝试将img元素绑定到属性( ProductImageUrl ),这是嵌套的ko.computed对象( MostPopularProduct )的属性,这是一个父ko.computed对象的属性( SelectedGroup )。

viewModel.SelectedGroup().MostPopularProduct().ProductImageUrl

当页面加载时,一切都按预期工作,数据绑定到图像工作。但是,当我单击Group2按钮时,我收到以下数据绑定错误:

Uncaught TypeError: Unable to parse bindings.
Bindings value: attr:{src: SelectedGroup().MostPopularProduct().ProductImageUrl}
Message: undefined is not a function VM133:3

嵌套的ko.computed属性MostPopularProduct()具有一个值并在页面加载时正确绑定,但在按钮单击后,在更新了父计算属性后,嵌套的ko.computed属性MostPopularProduct()未定义。

我怀疑该问题与viewModel属性的数据绑定有关,该属性是嵌套的ko.computed属性的属性。

这是jsfiddle: http://jsfiddle.net/boaldave/n5KQr/9/

<div id="GroupSelector">
    <img data-bind="attr:{src: SelectedGroup().MostPopularProduct().ProductImageUrl}">

    <ul id="Menu" data-bind="foreach:Groups">
        <li>
            <button data-bind="click: $parent.HandleButtonClick">
                <span data-bind="text: $data.GroupName"></span>
            </button>
        </li>
    </ul>
</div>

<script>

viewModel = {
    Groups: 
    [
        {
            GroupName:"Group1",
            MostPopularProductID: "Product1"
        },
        {
            GroupName:"Group2",
            MostPopularProductID: "Product2"
        }
    ],
    Products:
    [
        {
            ProductID: "Product1",
            ProductImageUrl: "http://placehold.it/100x100"
        },
        {
            ProductID: "Product2",
            ProductImageUrl: "http://placehold.it/200x200"
        }
    ]
};

// Since the data model above comes from a database, I extend the 
// viewModel properties with ko.observable and ko.computed properties:

viewModel.SelectedGroupName = ko.observable("Group1");

viewModel.SelectedGroup = ko.computed(function() {
    return ko.utils.arrayFirst(viewModel.Groups, function(item) {
        return item.GroupName === viewModel.SelectedGroupName();
        });
    }, viewModel);

viewModel.SelectedGroup().MostPopularProduct = ko.computed(function ()  {
    return ko.utils.arrayFirst(viewModel.Products, function (item) {
        return item.ProductID === viewModel.SelectedGroup().MostPopularProductID;
        });
    }, viewModel);

viewModel.HandleButtonClick = function(s, e) {
    viewModel.SelectedGroupName(s.GroupName);
};

var groupSelectorDiv = document.getElementById('GroupSelector');
if (groupSelectorDiv) {
    ko.applyBindings(viewModel, groupSelectorDiv);
}

</script>

1 个答案:

答案 0 :(得分:1)

JSFiddle:http://jsfiddle.net/jhmRc/

尝试更改

viewModel.SelectedGroup().MostPopularProduct = ko.computed(function ()  {

viewModel.SelectedGroup.MostPopularProduct = ko.computed(function ()  {

并更改此

<img data-bind="attr:{src: SelectedGroup().MostPopularProduct().ProductImageUrl>

<img data-bind="attr:{src: SelectedGroup.MostPopularProduct().ProductImageUrl}>

在您的示例中,您将MostPopularProduct分配给computed的值,这就是它在页面加载时起作用但在值更改后不起作用的原因。

第二种方法是将它添加到计算对象本身