2017-01-27 4 views
1

У меня есть модуль в моем приложении для нокаута, где я хочу иметь структуру типа дерева с флажками. То, что я пытаюсь достичь, заключается в следующем:Knockout JS treeview с флажками

  • Если я выбрал дочерние объекты, все родительские и грандиозные родители в этом узле будут выбраны, но с другим значком. Что-то вроде этого enter image description here
  • Если пользователь выбирает родителя все его дети выбирают, как этот enter image description here

Перед началом сделать свой собственный плагин для него, действительно Нокаут имеют ничего похожего на это, что я могу использовать в качестве основание и основываться на нем?

+0

обычно вы используете любой плагин в вас хотят как jstree или что-то, а потом писать пользовательские привязки для него. http://knockoutjs.com/documentation/custom-bindings.html. Еще одним вариантом является Oracle JET, основанная на нокауте, в которой есть множество компонентов. http://www.oracle.com/webfolder/technetwork/jet/index.html –

+1

вот скрипка, которую я играл с помощью http://jsfiddle.net/47d6r/384/, но я бы хотел вызвать функцию рекурсивно , Я собираюсь задать дополнительный вопрос об этом при переполнении стека. –

+1

здесь одно и то же, но вызывающее его рекурсивно http://jsfiddle.net/47d6r/387/ –

ответ

2

Я считаю, что использование некоторой библиотеки, подключенной к элементам DOM, как jstree - плохой подход. ИМХО лучше отделить модель данных и ее интерпретацию в htlm.

вот пример: 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"} 
]));