Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
536 views
in Technique[技术] by (71.8m points)

knockout.js - KnockoutJS ObservableArray data grouping

Does KnockoutJS have a feature whereas I could take something like:

    var myArray = ko.observableArray([
      { name: "Jimmy", type: "Friend" },
      { name: "George", type: "Friend" },
      { name: "Zippy", type: "Enemy" }
    ]);

Then select distinct on the "type" field, producing a result which looks like this:

(pseudo code)
    var distinct = myArray.distinct('type')
      // Returns array of two arrays
      //  distinct[0] is an array of type=Friend
      //  distinct[1] is an array of type=Enemy 

I'm aware of ko.utils.arrayGetDistinctValues, but that doesn't exactly do what I want. I'm also aware that I could write a few loops using ko.utils.arrayGetDistinctValues to get what I want, I'm just wondering if there is something else baked into KnockoutJS that I'm overlooking.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There is not anything else built into KO to make this any easier.

There are many ways that you could make this work. For example, you could extend observableArrays to have a distinct function. Then, you can just create your observableArray like:

this.people = ko.observableArray([
       new Person("Jimmy", "Friend"),
       new Person("George", "Friend"),
       new Person("Zippy", "Enemy")
]).distinct('type');

The distinct function might look like:

ko.observableArray.fn.distinct = function(prop) {
    var target = this;
    target.index = {};
    target.index[prop] = ko.observable({});    

    ko.computed(function() {
        //rebuild index
        var propIndex = {};

        ko.utils.arrayForEach(target(), function(item) {
            var key = ko.utils.unwrapObservable(item[prop]);
            if (key) {
                propIndex[key] = propIndex[key] || [];
                propIndex[key].push(item);            
            }
        });   

        target.index[prop](propIndex);
    });

    return target;
};    

It supports chaining so you could call distinct multiple times with different properties.

Sample here: http://jsfiddle.net/rniemeyer/mXVtN/

This does rebuild the index once on each change, so if you have a huge list of items, then you would want to potentially explore other ways (manual subscriptions) for adding/removing items from the "index" arrays.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...