knockout toggle嵌套项的可见性

时间:2014-03-18 20:05:36

标签: javascript knockout.js

我正在尝试使用Knockout切换嵌套项的可见性。在页面的初始显示中,我不希望嵌套项目可见。如果用户单击链接以显示嵌套项,那么我希望显示这些嵌套项(不是所有嵌套项)。

例如,我有一个产品列表,每个产品我都有星级评分列表。默认情况下或初始页面加载时,不显示评级。如果用户点击"评级",则会显示该项目的评分。如果用户点击"评分"对于其他项目,则显示该产品的评级以及另一个评级。

为了说明,我有两个产品:

三星评级

iPhone 评分

如果我点击iPhone的评级,则会显示iPhone评级:

Samsung Ratings       
iPhone Ratings
    1203: 3
    1204: 2

如果我点击三星的评级,那么三星的评级也会显示:

Samsung Ratings
    1201: 5
    1202: 4
iPhone Ratings
    1203: 3
    1204: 2

然后,如果我点击其中任何一个的评级,该产品的评级将变得不可见。

我的示例HTML如下:

<ul data-bind="foreach: products">
    <li><span data-bind="text: ProductName"></span>
        <a href="#" data-bind="click: $parent.toggleVisibility">Ratings</a> 
        <ul data-bind="foreach: StarRatings, visible: $parent.shouldShowRatings">
            <li><span data-bind="text: RatingId"></span>: <span data-bind="text: RatingValue"></span></li>
        </ul>
        </li>
</ul>

使用Knockout.js 3.0.0的示例javascript如下:

var initialProducts = [{ 
    ProductName: "Samsung", 
    StarRatings: [{ 
        RatingId: 1201, 
        RatingValue: 5
        },
        { 
            RatingId: 1202, 
            RatingValue: 4
        }
    ]
}, {
    ProductName: "iPhone", 
    StarRatings: [{ 
        RatingId: 1203, 
        RatingValue: 3
        },
        { 
            RatingId: 1204, 
            RatingValue: 2
        }
    ]
}];

(function (ko) {
    function products(data) {

        var self = this;
        data = data || {};

        // Persisted properties
        self.ProductId = data.ProductId;       
        self.StarRatings = data.StarRatings;
    }    
})(ko);

var viewModel = (function(ko){
    var products = ko.observableArray(initialProducts),
        showRatings = ko.observableArray(),
        toggleVisibility = function(item) {
            if(showRatings.indexOf(item) < 0){
                showRatings.push(item);
            } 
            else{
                showRatings.remove(item);
            }
        },
        shouldShowRatings = function(item) {
            if( showRatings.indexOf(item) >= 0){
                return true;
            }
            {
                return false;
            }
        };

    return {
        products: products,
        showRatings: showRatings,
        toggleVisibility: toggleVisibility,
        shouldShowRatings: shouldShowRatings
    };
})(ko);

ko.applyBindings(viewModel);

我已经能够显示所有评分或没有显示。我也能够将其设置为一次只显示一个,但我认为这段代码最接近我需要的解决方案。

看起来在点击事件之后,不会为StarRatings可见性调用 shouldShowRatings 以查看可见性。

示例代码也位于http://jsfiddle.net/justinnafe/866my/4/

的jsFiddle上

2 个答案:

答案 0 :(得分:2)

只需更新您的绑定,以$ data作为第一个参数调用函数:http://jsfiddle.net/866my/6/

<ul data-bind="foreach: products">
    <li><span data-bind="text: ProductName"></span>
        <a href="#" data-bind="click: $parent.toggleVisibility($data)">Ratings</a> 
        <ul data-bind="foreach: StarRatings, visible: $parent.shouldShowRatings($data)">
            <li><span data-bind="text: RatingId"></span>: <span data-bind="text: RatingValue"></span></li>
        </ul>
    </li>
</ul>

重要的是你使用函数表示法来获取绑定以检查更新。

答案 1 :(得分:1)

修复初始评估的更好方法是使用标准ko方式: http://jsfiddle.net/866my/10/

变化

<a href="#" data-bind="click: $parent.toggleVisibility($data)">Ratings</a>

<a href="#" data-bind="click: $parent.toggleVisibility">Ratings</a>

现在ko得到一个函数对象(toggleVisibility函数),在你点击它之前它不会调用它。

ko默认将当前上下文$ data作为第一个参数传递给目标函数,因此不需要显式调用($ data)。