Knockout复选框选择过滤器

时间:2013-06-22 09:49:12

标签: javascript jquery knockout.js viewmodel

我是knockoutjc图书馆的新手,你能帮助我吗?我在这样的javascript中创建了一个新模型。

enter image description here

代码在这里:

        <h2>Category : Throusers</h2>

    <h3>Sizes</h3>
    <ul data-bind="foreach: products">
        <li>
            <input type="checkbox" data-bind="value: size.id" />
            <label data-bind="text: size.name"></label>
        </li>
    </ul>

    <h3>Colors</h3>
    <ul data-bind="foreach: products">
        <li>
            <input type="checkbox" data-bind="value: color.id" />
            <label data-bind="    text: color.name"></label>
        </li>
    </ul>

    <h3>Products</h3>
    <ul data-bind="foreach: products">
        <li>
            <label data-bind="text: name"></label> - 
            <label data-bind="text: size.name"></label>-
            <label data-bind="text: color.name"></label>
        </li>
    </ul>

    <script type="text/javascript">

        function Color(id, name) {
            return {
                id: ko.observable(id),
                name: ko.observable(name)
            };
        };

        function Size(id, name) {
            return {
                id: ko.observable(id),
                name: ko.observable(name)
            };
        }

        function Product(id,name, size, color) {
            return {
                id: ko.observable(),
                name: ko.observable(name),
                size: size,
                color: color
            };
        };

        var CategoryViewModel = {
            id: ko.observable(1),
            name: ko.observable("Throusers"),
            products: ko.observableArray([
                new Product(1,"Levi's 501", new Size(1, "30-32"), new Color(1, "Red")),
                new Product(2,"Colins 308", new Size(2, "32-34"), new Color(2, "Black")),
                new Product(3,"Levi's 507", new Size(1, "30-32"), new Color(3, "Blue"))
            ])
        };

        ko.applyBindings(CategoryViewModel);
    </script>

现在,

  1. 我想这样:重复的尺寸和颜色不应该列出。
  2. 当我从颜色中选择颜色时,应列出所选颜色的产品,并禁用其他产品
  3. 如果型号错了?

2 个答案:

答案 0 :(得分:1)

不要在产品型号上存储尺寸和颜色,而应将它们分开存储 - 就像标准化数据库一样。

仅存储产品型号中可用尺寸和颜色的ID。

颜色列表和尺寸列表的foreach应该迭代尺寸模型中的所有尺寸和颜色模型中的所有颜色。

visible绑定添加到产品列表中。如果产品具有尺寸ID和颜色ID,则返回true。

最后,我可能还会将产品型号的尺寸和颜色属性设置为数组,以便每种产品都可以有多种颜色和尺寸。

答案 1 :(得分:1)

我试图解决你的问题。 我从零开始写了一切,看一看。可能有一些错误,没有时间对它进行大量测试。但您现在可以轻松添加所需的任何自定义过滤器。

http://jsfiddle.net/blackjim/8y5PP/12/

    //    jQuery 1.10 loaded

var myAPP = (function($,ko){

    // trouserModel constructor
    var TrouserModel = function(id,name,color,size,visible){
        // maybe better if fields are ko observable, depends on other details
        this.id = id||0,
        this.name = name||'',
        this.color = color||'',
        this.size = size||'',
        this.visible = visible||true;

        return ko.observable(this);
    }

    // main viewmodel
    var trouserProducts = {
        data: ko.observableArray(),
        filters: ko.observableArray()
    }

    trouserProducts.sizeFilter = ko.computed(setFilter('size'));
    trouserProducts.colorFilter = ko.computed(setFilter('color'));
    trouserProducts.updateFilter = function(element, valueAccessor, allBindingsAccessor) {

        var ar = trouserProducts.data();
        if(!ar[0]) return true;
        var activeFilters = trouserProducts.filters().filter(function(el){return el().on;});

        for(var i=0; i<ar.length; i++){

            for(var j=0; j<activeFilters.length; j++){
                var thisProp = ar[i]()[activeFilters[j]().prop].toLowerCase();

                if( thisProp===activeFilters[j]().value ){
                    var that = ar[i]();

                    ar[i]({
                        id: that.id,
                        name: that.name,
                        color: that.color,
                        size: that.size,
                        visible: true
                    });
                    break;
                }
            }
            if( j===activeFilters.length ){
                var that = ar[i]();

                ar[i]({
                    id: that.id,
                    name: that.name,
                    color: that.color,
                    size: that.size,
                    visible: false
                });
            }
        }

        return true;
    };

    // helper functions
    var makeFilter = function(prop,value){
        var ar = trouserProducts.filters()
            value = value.toLowerCase();    //    normalize values (OPTIONAL)

        for(var i=0; i < ar.length ;i++){
            var that = ar[i]();

            if(that.prop===prop && that.value===value){
                that.on = true;
                return false;
            }
        }

        // add filter
        trouserProducts.filters.push(ko.observable({ 
            prop: prop,
            value: value,
            on: true,
            updateFilter: function(){
                trouserProducts.updateFilter();
                return true;
            }
        }));
    }

    // return a function with a specific filter
    function setFilter(prop){
        var prop = prop,
            propFilter = function(el,i,ar){
                // el is ko observable filter here
                return el().prop === prop;
            };

        return function(){            
            return trouserProducts.filters().filter(propFilter);
        }
    };

    var addTrouser = function(id,name,color,size){
        var newTrouser = new TrouserModel(id,name,color,size);
        color && makeFilter('color',color);  // make color filter
        size && makeFilter('size',size);     // make size filter
        trouserProducts.data.push(newTrouser);  // add new trouserModel
    }

    return {
        trouserProducts: trouserProducts,
        addTrouser: addTrouser
    }
}(jQuery,ko));

// add your initial products here
myAPP.addTrouser(1,"Levi's 501","Red","30-32");
myAPP.addTrouser(2,"Levi's 507","Black","32-34");
myAPP.addTrouser(3,"Levi's 507","Black","30-32");
myAPP.addTrouser(4,"Dirty jeans","Blue","32-34");
myAPP.addTrouser(5,"Dirty jeans","Red","32-34");

ko.applyBindings(myAPP.trouserProducts);

window.myAPP = myAPP;