2012-05-29 3 views
2

KnockoutJS를 사용하고 있는데 observableArray의 관찰 가능 객체가 부모에게 변경 사실을 알릴 수있는 방법을 알고 싶습니다.변경 사항을 부모에게 알리는 방법

http://jsfiddle.net/paragnair/CEEZ5/

HTML :

<h1 id="heading"> <text data-bind="text:childrenCount"></text> Fields selected</h1> 
<table id="form"> 
<tbody data-bind="foreach:children"> 
    <tr> 
     <td data-bind="text:name"></td> 
     <td><input type="checkbox" data-bind="checked:isSelected"/></td> 
    </tr> 
</tbody> 
</table> 

<a href="#" id="btn-add">Add More Fields</a>​ 

자바 스크립트 예를 들면 다음과 같습니다 위의 예에서

var Child = function(name) { 
    var self = this; 
    self.name = ko.observable(name); 
    self.isSelected = ko.observable(false); 
}, 
    Parent = function() { 
     var self = this; 
     self.children = ko.observableArray([ 
      new Child('One'), 
      new Child('Two'), 
      new Child('Three') 
      ]); 
     self.children.subscribe(function(children) { 
      header.childrenCount($.map(children, function(a) {     
       return a.isSelected() ? 1 : null; 
      }).length); 
     }); 
    }, 
    header = { 
     childrenCount: ko.observable(0) 
    }; 

var parentModel = new Parent(), 
    extra = parentModel.children().length; 
ko.applyBindings(parentModel, $('#form')[0]); 
ko.applyBindings(header, $('#heading')[0]); 

function setHeading(childrenCount) { 
    header.childrenCount(childrenCount); 
} 

$(document).ready(function() { 
    $('#btn-add').click(function() { 
     extra++; 
     parentModel.children.push(new Child('Extra ' + extra)); 
     return false; 
    }); 
});​ 

, 내가 선택한 필드의 수와 제목을 표시합니다. observableArray에 대해 subscribe 이벤트가 있지만 배열에서 항목을 추가하거나 제거 할 때만 발생하므로 사용자가 필드 목록의 체크 박스를 실제로 검사 할 때 이벤트가 시작되지 않습니다. 이를 달성하는 한 가지 방법은 확인란에 onchange 이벤트를 추가하여 부모에서 메서드를 호출하는 것입니다.이 메서드는 header 개체의 childrenCount을 업데이트하는 외부 메서드를 호출합니다. 이 작업을 수행하는 더 좋은 방법이 있습니까?

답변

2

마지막으로 서브 스크립 션을 사용하지 않았지만 data-bindevent을 사용하고 차례로 외부 기능 setHeading을 호출합니다. 업데이트 된 바이올린은 다음과 같습니다. http://jsfiddle.net/paragnair/CEEZ5/5/

6

나는 당신이 다른 방식으로 이것을 접근 할 수 있고 동시에 불필요한 합병증을 제거 할 수 있다고 생각합니다. 모델을 별도의 applyBindings 호출로 분리 할 필요는 없습니다. 사실, 합병증이 추가되고 조심하지 않으면 이중 바인딩이 생길 수 있기 때문에 절대적으로 필요한 경우가 아니라면이 방법을 권장하지 않습니다.

두 번째로, 헤더가 parentModels 하위의 결과이면 실제로는 동일한 모델의 일부 여야하며 OOP 원리는 KO 모델을 작성할 때 적용될 수 있고 적용되어야합니다. 이것은 처음부터 KO를 사용하는 장점이 있습니다.

다음은 문제를 해결하는 방법입니다.

http://jsfiddle.net/madcapnmckay/edJyp/

var Child = function(name) { 
    var self = this; 
    self.name = ko.observable(name); 
    self.isSelected = ko.observable(false); 
}, 
Parent = function() { 
    var self = this; 
    self.children = ko.observableArray([ 
     new Child('One'), 
     new Child('Two'), 
     new Child('Three') 
     ]); 

    this.childrenCount = ko.computed(function() { 
     var count = 0; 
     ko.utils.arrayForEach(self.children(), function (child) { 
      if (child.isSelected()) { 
       count++; 
      } 
     }); 
     return count; 
    }); 

    this.addMore = function() { 
     self.children.push(new Child("Extra " + (self.children().length + 1))); 
    }; 
}; 

var ViewModel = function() { 
    var self = this; 
    this.parentModel = new Parent(); 
}; 

ko.applyBindings(new ViewModel()); 

참고 뷰 모델 클래스는 불필요하지만 난 당신이에 태그 것 여기에 표시되는 것보다 더 많은 기능을 가지고 가정입니다.

제쳐두고 왜 jquery 클릭 핸들러를 버튼에 사용해야 할 필요가 있다고 생각하십니까? 나는이 실수를 자주보고 문서에서 당신이 그 길을 이끌어 갈지 궁금해하고 있었습니까? 이것은 예제에서 수행 한 viewModel로 이동할 수도 있고 옮길 수도 있습니다.

희망이 도움이됩니다.

+0

아쉽게도 내 응용 프로그램에서 설계된 방식대로 applyBindings를 별도로 유지해야합니다. 그래서 배열 내의 obserbale 객체의 값이 업데이트 될 때마다 외부 함수를 호출 할 방법이 필요합니다. 단추에 대한 클릭 핸들러의 경우,이 예제는 내 실제 프로젝트가 아닙니다. – Wiz

관련 문제