Knockout JS treeview with checkboxes

2019-07-25 20:28发布

I have a module in my knockout application where I want to have a tree type structure with checkboxes. What I am trying to achieve with that is the following

  • If I select child all the parent and grand parents in that node gets selected but with a different icon. Something like this enter image description here
  • If the user selects the parent all its children are selected like this enter image description here

Before starting to make my own plugin for it, does knockout have anything similar to this, which I can use as a base and build upon it?

1条回答
淡お忘
2楼-- · 2019-07-25 20:52

i believe using some library hooked to DOM elements like jstree is bad approach. IMHO it is better to separate data model and its interpretation in htlm.

here is example: https://jsfiddle.net/gqyk1ssh/

ko.bindingHandlers.prop = {
    update: function(element,valueAccessor) {
        var props = ko.toJS(valueAccessor());
        for (prop in props){
            element[prop] = ko.unwrap(props[prop]);
        }
    }
}


function model(folders){
    this.folders = ko.observableArray(ko.utils.arrayMap(folders,function(folder){
        return new modelFolder(folder);
    }));
};


function modelFolder(folder,parent){
    this.name = ko.observable(folder.name);
    this.checked = ko.observable(folder.checked);
    this.parent = parent;

    this.folders = ko.observableArray(
        folder.folders ?
            ko.utils.arrayMap(folder.folders,function(folder){
                return new modelFolder(folder,this);
            }.bind(this))
            : null
    );

    this.checkedChildFolders = ko.pureComputed(function(){
        return ko.utils.arrayFilter(this.folders(),function(folder){
            return folder.checked() || folder.checkedAllChildFolders() || folder.checkedSomeChildFolders()
        });
    },this)

    this.checkedSomeChildFolders = ko.pureComputed(function(){
        return this.folders().length>0 && !this.checkedAllChildFolders() && this.checkedChildFolders().length > 0 
    },this);

    this.checkedAllChildFolders = ko.pureComputed(function(){
        return this.folders().length>0 && this.checkedChildFolders().length == this.folders().length
    },this)  
}

modelFolder.prototype.setCheck = function(check){
    this.checkParents(check);
    this.checkMeAndChildrens(check);
}

modelFolder.prototype.checkMeAndChildrens = function(check){
    this.checked(check);
    ko.utils.arrayForEach(this.folders(),function(folder){
        folder.checkMeAndChildrens(check);
    });
}   

modelFolder.prototype.checkParents = function(check){
    if(this.parent){
        this.parent.checked(check);
        this.parent.checkParents(check);
    }
}


ko.applyBindings(new model([
    {"name":"Lorem", "folders":[
        {"name":"Dolor","folders":[
            {"name":"Hello","folders":[
                {"name":"Lorem"},
                {"name":"Dolor","checked":true},
                {"name":"Sit amet"}
            ]},
            {"name":"Bye"},
        ]},
        {"name":"Sit amet"}
    ]},
    {"name":"Ipsum"}
]));
查看更多
登录 后发表回答