2012-07-13 2 views
5

knockoutjs를 사용하여 디비전 트리 뷰를 만듭니다. 각 노드 옆에는 세 개의 버튼이 있습니다 : 1) 새로운 자식 (2 옆에있는 노드에 적용) 제거 (옆에있는 노드를 제거합니다.) 3) 복사 : 노드와 노드를 모두 복사하고 새로운 노드를 만듭니다. 노드를 부모 아래에 두십시오.knockoutJS의 observableArray에서 셀프 제거

나는 새로운 버튼을 가지고 있고, 이제 나는 제거 버튼을 만들고있다. 나는 제대로 작동하지 않는 것 같아서 유용하게 사용하는 대신 전체 페이지를 새로 고침 만합니다. 여기 코드는 다음과 같습니다

보기 :

<h2>Skill & Weight Divisions</h2> 
     <span data-bind="text: tournamentname"></span><button data-bind="click: addDivision"><img src="new.png"/></button> 
     <ul data-bind="template: { name: 'divisionTemplate', foreach: divisions }"></ul> 

템플릿 :

<script id="divisionTemplate" type="text/html"> 
    <li data-bind="style: {'background-color':color}"> 
     <input data-bind="value: name"/><button data-bind="click: addDivision"><img src="new.png"/></button><button data-bind="click: $parent.removeDivision"><img src="remove.png"/></button><button data-bind="click: $parent.copyDivision"><img src="copy.png"/></button> 
     <ul data-bind="template: { 'if': children, name: 'divisionTemplate', foreach: children }"></ul> 
    </li>  
</script> 

보기 모델 및 적절한 도우미 기능 :

function division(id, name, filter, children) { 
     this.id = ko.observable(id); 
     this.name = ko.observable(name); 
     this.filter = ko.observable(filter) 
     if(children){ 
      this.children = ko.observableArray(children); 
     }else{ 
      this.children = ko.observableArray(); 
     } 
     this.addDivision = function(){ 
      this.children.push(new division("", "", "")); 
     } 
     this.removeDivision = function(division){ 
      this.children.remove(division); 
     } 
     this.copyDivision = function(division){ 
      this.children.push(division); 
     } 
     this.color = randColor(); 
    }; 
    function tournamentViewModel(){ 
     var self= this; 
     self.tournamentname = ko.observable('NO NAME YET'); 
     self.districts = ko.observableArray([new district('Provo',1),new district('Salt Lake City',2),new district('St. George',3)]); 
     self.district = ko.observable(self.districts()[0]); 
     self.regions = ko.observableArray([new region('Utah',1),new region('Idaho',2)]); 
     self.region = ko.observable(self.regions()[0]); 
     self.location = ko.observable('WHEREVER YOU WANT'); 
     self.eventdate = ko.observable(''); 
     self.startTime = ko.observable(''); 
     self.image = ko.observable(); 
     self.flyer = ko.computed(function(){ 
      var flyerHTML = '<span style="text-align:center;padding:10px;"><h1>'+self.tournamentname()+'</h1><img src="'+self.image()+'"/><br/>'; 
      flyerHTML += 'District: ' + self.district().districtName + ' Region: ' + self.region().regionName+'<br><br>'; 
      flyerHTML += '<h2>WHEN: '+self.eventdate()+' '+self.startTime()+'</h2>'; 
      flyerHTML += '<h2>WHERE: '+self.location()+'</h2>'; 
      flyerHTML += '<img src="http://maps.googleapis.com/maps/api/staticmap?center='+encodeURI(self.location())+'&zoom=12&size=200x200&markers=color:blue%7Clabel:S%7C'+encodeURI(self.location())+'&maptype=roadmap&sensor=false"/>'; 
      return flyerHTML; 
     }, self); 
     self.clearImage = function(){ 
      self.image(''); 
     } 
     self.tournamentID = ko.computed(function(){return 't_'+self.district()+'_'+self.region()+'_'+self.eventdate()}, self); 
     self.pricingStructures = ko.observableArray([new pricingStructure(3,2.99), new pricingStructure(1,1.99)]); 
     self.removePricingStructure = function(pricingStructure){ 
      self.pricingStructures.remove(pricingStructure); 
     } 
     self.addPricingStructure = function(){ 
      self.pricingStructures.push(new pricingStructure("", "")); 
     } 
     self.promoCodes = ko.observableArray(); 
     self.promoTypes = ['%','$']; 
     self.removePromoCode = function(promoCode){ 
      self.promoCodes.remove(promoCode); 
     } 
     self.addPromoCode = function(){ 
      self.promoCodes.push(new promoCode("", ""));  
     } 
     self.divisions = ko.observableArray([new division(1, "Men","",[new division(2,"Gi"), new division(3,"No-Gi")])]); 
     self.addDivision = function(){ 
      self.divisions.push(new division("", "", "")); 
     } 

    } 
    ko.applyBindings(new tournamentViewModel()); 

이 모든 나의 주요 질문은 이것이다 : 배열에서 바로 객체를 제거하기 위해 객체의 부모 배열에 액세스하는 방법이 있습니까? 도움에 미리 감사드립니다!

편집 : 여기는 jsFiddle : http://jsfiddle.net/eqY7Z/입니다. 그러나 전혀 작동하지 않는 것 같습니다. 너희들이 그것을 얻을 수 없다면, 나는 당신이 그것을 잘 볼 수 있도록 호스트되는 사이트에 대한 링크를 포함시킬 것이다.

+0

또한 필자는 일부 지점에서 제거 작업을 수행했지만 두 단계 만 추가한다고 덧붙이고 싶습니다. 더 깊은 것은 효과가 없었습니다.거기에서 일한 코드를 기억하면 알려 드리겠습니다. –

+1

jsfiddle을 만들 수 있습니까? – HashCoder

+0

나는 지금 일하러 가야하지만, 내 휴식 시간에 나는 하나를 올려 놓을 것이다. –

답변

2

나는 당신의 생각을 털어 정확히 설명한대로 행동하는 working fiddle을 만들었습니다. 나는 너를 정리하려고하지 않았어. 미안해. 그것은 당신의 문제와 직접적인 관련이없는 많은 것들을 가지고 있었고,이 솔루션은 다른 사람들이 그것을 사용할 수 있어야만하는 일반적인 것입니다. 적응하는 데 도움이 필요하면 알려주세요.

주목할 점은 클론 기능입니다. 복사 기능이 깊지 않아 여러 노드가 동일한 객체를 가리키게됩니다. 노드 값을 업데이트하려면 해당 노드 값이 복제본에 전파됩니다. 넉 아웃은 ko.toJS과 함께 유용한 깊은 사본 + unwrap observables를 제공합니다. 매우 유용합니다.

JS :

var Node = function(name, children) { 
    var self = this; 
    self.name = ko.observable(name || 'NewNode'); 
    self.children = ko.observableArray(
    ko.utils.arrayMap(children || [], function(i) { 
     return new Node(i.name, i.children); 
    })); 
    self.newChild = function() { 
     self.children.push(new Node()); 
    }; 
    self.removeNode = function(node) { 
     self.children.remove(node); 
    }; 
    self.copyNode = function(node) { 
     var cloneNode = ko.toJS(node); 
     self.children.push(new Node(cloneNode.name, cloneNode.children)); 
    }; 
}; 

//Example data removed for brevity, see fiddle 
ko.applyBindings(new Node(data.name, data.children));​ 

HTML : http://jsfiddle.net/3eQNf/ : 나는 다음과 같은 jsFiddle에서 코드의 작업 버전을 만들 수 있었다

<button data-bind="click: newChild">NewNode</button> 
<ul data-bind="template: { name: 'treeTemplate', foreach: children}"> 
</ul> 

<script id="treeTemplate" type="text/html"> 
    <li> 
     <input data-bind="value: name" /> 
     <button data-bind="click: newChild">New Child</button> 
     <button data-bind="click: $parent.removeNode">Remove Node</button> 
     <button data-bind="click: $parent.copyNode">Copy Node</button> 
     <ul data-bind="template: { name: 'treeTemplate', foreach: children}"></ul> 
    </li> 
</script> 
​ 
+0

이것은 멋지다. 그리고 나는 오늘 밤에 그것을 나중에 시험해 볼 것이다. 당신이 일반적인 대답으로 이것을 썼다는 것을 알기 때문에 분명히 말하자면, 제 특정한 경우에 노드들은 제가 부서라고 부를 것입니다, 맞습니까? –

+0

예. 노드는 트리의 항목에 대한 공통 용어입니다. – Tyrsius

+0

복사 기능도 너무 많이 가져 주셔서 감사합니다. 나는 제거 기능을 무효화 한 후에 그것을 할 것입니다. 저에게 시간을 절약하고 저에게 좋은 녹아웃 자바 스크립트를 가르쳐 주셔서 감사합니다! –

1

. 다음과 같은 두 가지 주요 문제가 발생했습니다.

  1. 부서 클래스에서 "this"키워드를 사용하는 데 문제가 있습니다. 자기 변수를 추가하면 그 문제가 해결됩니다.

  2. 단일 루트 수준 나누기를 추가하고 해당 자식을 바인딩해야했습니다. 이렇게하면 모든 재귀가 예상대로 작동합니다. 이것은 또한

는 또한, 참고로, 내가 지구, 지역의 스텁을 추가 할 필요가 떨어져 당신의 tournamentViewModel의 addDivision 방법에 대한 필요성을 제거하고, 그 이후 pricingStructure 클래스는 위의 샘플 코드에 포함되지 않았다. 희망이 도움이됩니다.

+0

무엇이 잘못되었는지 알려 주셔서 감사합니다. 지구, 지역 등의 코드를 삭제했다고 생각했습니다. 오 잘. 나는 당신이 제공 한 바이올린으로 최상위 부문을 복사 할 수는 없지만, 실제로는 기존의 객체를 가리키는 텍스트 상자를 생성한다는 사실을 알았습니다. 제 질문은 복사에 관한 것이 아니라 단지 당신을 위해 그것을 지적하고 싶었습니다. –