2013-07-22 4 views
0

현재 녹아웃 용 Josh Buckley의 Datatables 바인딩을 사용하고 있습니다. 나는 데이터 테이블에 "행 삭제"버튼을 만들려고합니다. 현재 각 버튼에 클릭 데이터 바인딩이 있습니다. 데이터 테이블 소스는 관찰 가능한 배열에 연결됩니다. 사용자가 버튼을 클릭하면 관찰 가능 어레이에서 객체가 제거되고 업데이트 바인딩이 트리거되고 이후에 테이블 뷰가 업데이트됩니다. 적어도 버튼을 클릭 할 때마다 정상적으로 작동합니다.Knockout + Datatables - 셀의 바인딩 업데이트

그러나 테이블이 업데이트되면 "행 삭제"버튼의 모든 클릭 바인딩이 작동을 멈 춥니 다. 업데이트 바인딩이 호출 될 때마다 전체 테이블이 지워지고 다시 작성되므로 바인딩이 새 요소에 적용되지 않기 때문입니다.

각 데이터 테이블 업데이트로 생성 된 새 요소를 리 바인드하려면 어떻게해야합니까? 또는 이것을 처리하는 더 좋은 방법이 있습니까?

사용자 정의 바인딩 :

(function($){ 
    ko.bindingHandlers.dataTable = { 
     init: function(element, valueAccessor){ 
      var binding = ko.utils.unwrapObservable(valueAccessor()); 

      // If the binding is an object with an options field, 
      // initialise the dataTable with those options. 
      if(binding.options){ 
       $(element).dataTable(binding.options); 
      } 
     }, 
     update: function(element, valueAccessor){ 
      var binding = ko.utils.unwrapObservable(valueAccessor()); 

      // If the binding isn't an object, turn it into one. 
      if(!binding.data){ 
       binding = { data: valueAccessor() } 
      } 

      // Clear table 
      $(element).dataTable().fnClearTable(); 

      // Rebuild table from data source specified in binding 
      $(element).dataTable().fnAddData(binding.data()); 
     } 
    }; 
})(jQuery); 

HTML 코드 :

<table id="membersTable" class="table table-striped table-bordered bootstrap-datatable datatable" data-bind="dataTable: membersTable"> 
    <thead> 
     <tr> 
      <th>Name</th> 
      <th>Actions</th> 
     </tr> 
    </thead> 
</table> 

보기 모델 :

var groupViewModel = { 
    groupMembers: ko.observableArray([ 
     new GroupMember("1", "Abe", true), 
     new GroupMember("2", "Bob", false), 
     new GroupMember("3", "Bill", false) 
    ]) 
}; 

groupViewModel.membersTable = ko.computed(function() { 
    var self = this; 

    var final_array = new Array(); 
    for(var i = 0; i < self.groupMembers().length; i++) 
    { 
     var row_array = new Array(); 
     row_array[0] = self.groupMembers()[i].nameWithLink(); 
     row_array[1] = self.groupMembers()[i].actions(); 
     final_array.push(row_array); 
    } 

    return final_array; 
}, groupViewModel); 

groupViewModel.removeMember = function(id) { 
    var self = this; 

    self.groupMembers.remove(function(groupMember) { 
     return groupMember.id == id; 
    }); 
}; 

그룹 회원 개체 :

function GroupMember(id, name, isGroupLeader) 
{ 
    var self = this; 
    self.id = id; 
    self.name = name; 
    self.isGroupLeader = ko.observable(isGroupLeader); 

    self.link = ko.computed(function() { 
     return "/#user/" + self.id; 
    }); 

    self.nameWithLink = ko.computed(function() { 
     return '<a href="' + self.link() + '">' + self.name + '</a>'; 
    }); 

    self.actions = ko.computed(function() { 
     return '<a class="btn btn-danger" data-bind="click: function() {removeMember(' + self.id + ')}">' + '<i class="icon-minus-sign"></i>' + '</a>'; 
    }); 
} 

편집 :

jsfiddle 링크 : http://jsfiddle.net/zongweil/PLUKv/1/

+0

당신은 이것을 바이올린에 넣을 수 있습니까? 도움을 훨씬 쉽게 해줍니다. –

+0

추가 : http://jsfiddle.net/zongweil/PLUKv/1/ – zongweil

답변

0

http://jsfiddle.net/PLUKv/4/

나는 데이터 테이블 바인딩 버클리들에 대해 잘 모르지만, 많은 문제가있다 당신이 게시 한 원래 바이올린에 나는 그 사람들을 만질 것이고 그래서 나는 왜 내가 게시 한 해결책이 더 나은 방법인지 볼 수있다. -

  1. 데이터에 일부 기능 (예 : 제거 또는 연결)을 제공하기 위해 배열 배열을 만들지 마십시오. 그것은 나쁜 습관이고 당신은 문제에 대해 스스로를 설정하고 있습니다. 뷰 모델에 데이터 레코드에 기능을 추가하는 것과 같은 일반적인 방법을 사용하거나 다른 많은 방법을 사용할 수 있지만 뷰 모델에 HTML을 추가하지 마십시오.

  2. 기능을 추가하려면보기 모델에서 데이터를 foreach 처리 할 필요가 없습니다. 녹아웃은 뷰에 필요한 도구를 제공하여 뷰 모델이 뷰에 대해 전혀 알 필요가 없도록 도와줍니다. 또한보기 모델 기능을보기에 넣지 마십시오. 나쁜 행동입니다 (HTML에 기능을 주입했기 때문에 더러운 것 같습니다!)

  3. 마지막으로보기 모델 기능을 모델에 넣지 마십시오. 당신의 뷰 모델은 무엇을위한 것인가!

로보기보다 빠르고 효율적으로 렌더링에서 - 그것은 직업이하자 -

<tbody data-bind="foreach: groupMembers"> 
    <tr> 
    <td><a data-bind="click: $parent.gotoPersonLink, text: name" /></td> 
    <td><button data-bind="click: $parent.removeMember"><i class="icon-remove" /></button></td> 
    </tr> 
</tbody> 

뷰 모델을 HTML 삽입하지 않고도 기능을 제공 할 수있는 기회 부여 -

self.removeMember = function (member) { 
    self.groupMembers.remove(member); 
}; 

self.gotoPersonLink = function (member) { 
    alert('add your change window logic here');  
}; 

멤버 제거와 같이 모델에 항상 기능을 추가 할 수는 있지만 코드가 필요한 것보다 999 번 더 많은 코드가 기록 된 1000 개의 레코드가있는 경우를 의미합니다. 그것은 말하기를, 만약 당신이 절대적으로 옛날 방식으로 돌아 가야한다면, 행운을 빌어 요! 그렇다면 Knockout에 의존하지 않아도됩니다.

+0

자세한 답변을 보내 주셔서 감사합니다! 나는이 경우에 약간 이상하게 구조화되어 있다는 것에 동의하지만, datatables 바인딩은 생성 된 행이 아닌 데이터 소스에서만 작동하기 때문에 그 것이다. 내가 게시 한 코드는 내 자신의 해결 방법이었습니다. 생성 된 행을 사용할 수 있도록 바인딩을 수정하는 것에 대한 제안 사항이 있습니까? 검색/필터링/페이지 매김을위한 datatable 기능이 필요합니다. – zongweil

+0

또한 논리 구조화에 대한 팁을 고맙게 생각합니다. 나는 몇 주 전에 Knockout을 집어 들었으므로 여전히 최선의 방법을 배우려고 노력하고있다 :). – zongweil

+0

조금만 검토 한 결과 좋았을 텐데요. 당신이 성취하고자하는 것을 수행하는 더 좋은 방법이 있음을 압니다.하지만, 불행하게도 Josh Buckley가 가지고있는 사이트를 검토 한 후에 아무 것도 작동하지 않고 찾고있었습니다. 더 나아가 커스텀 바인딩 핸들러가 모든 변경에 대해 테이블을 재생성하는 것으로 나타나 Knockout이 당신을 도우려는 데 도움이되지 않습니다. 누락 된 것으로 보이는 유일한 기능은 필터링 및 페이지 매김입니다. Breeze.js와 같은 라이브러리를 살펴 보았습니까? –

관련 문제