2011-09-08 5 views
4

knockoutjs를 사용하여 동적 쿼리 편집기를 코딩하고 있지만, ko.toJSON은 데이터 바인딩 폼 요소로 수정 될 때까지 필드를 출력하지 않습니다. 뷰 모델이 명확하게 (예 : 조인 속성으로) 사전이 초기화 필드가 비록 그들이에 표시되지있어,ko.toJSON이 필드를 무시하는 것처럼 보입니다.

// filter class 
var Filter = function() { 
    this.field = ko.observable(); 
    this.modifier = ko.observable(); 
    this.criteria = ko.observable(); 
}; 

// filter group class 
var FilterGroup = function() { 
    // Include a blank filter in every group 
    this.join = ko.observable('All'); 
    this.filters = ko.observableArray([new Filter()]); 
    this.addFilter = function() { 
     var filter = new Filter(); 
     this.filters().push(filter); 
     this.filters.valueHasMutated(); 
    }; 
    this.addGroup = function() { 
     var group = new FilterGroup(); 
     this.filters().push(group); 
     this.filters.valueHasMutated(); 
    }; 
}; 

// Data 
var joins = ['All', 'Any']; 
var modifiers = [ 
    'equals', 
    'not equal to', 
    'less than', 
    'greater than', 
    'contains', 
    'does not contain', 
    'starts with' 
]; 
var fields = ['f1','f2','f3']; 

var viewModel = new FilterGroup(); 
function dev(){ 
    return ko.toJSON(viewModel); 
} 

ko.applyBindings(viewModel); 

:

<span data-bind="template: {name: 'filterGroupTemplate', data: viewModel}"></span> 

<script type="text/x-jquery-tmpl" id="filterGroupTemplate"> 
    <div class="filterGroup"> 
     <div class="filterGroupParams"> 
      Match 
      <select name="join" data-bind="value: join, options: joins"></select> 
      of the following rules: 
      <button class="addFilter" data-bind="click: addFilter">+</button> 
      <button class="addGroup" data-bind="click: addGroup">{...}</button> 
      <button class="removeGroup">x</button> 
     </div> 
     <span data-bind='template: {name: "filterTemplate", foreach: filters }'></span> 
    </div> 
</script> 

<script type="text/x-jquery-tmpl" id="filterTemplate"> 
    <div class="filter"> 
     {{if $data.filters }}  
      <div data-bind='template: "filterGroupTemplate"'> 
      </div>     
     {{else}} 
      <select data-bind="value: field, options: fields"></select>  
      <select data-bind="value: modifier, options: modifiers"></select> 
      <input type="text" data-bind="value: criteria" /> 
      <button>x</button> 
     {{/if}} 
    </div> 
</script> 

<h2>ViewModel JSON</h2> 
<div data-bind="text: dev()"></div> 

그리고이 코드를 다음 볼 수있는 this jsfiddle를 참조하십시오 사용자가 UI에서 변경할 때까지 JSON 객체

누군가 내가 잘못하고있는 것과 해결 방법을 설명해 줄 수 있습니까? 이것은 실제로 knockoutjs 자체의 버그처럼 보입니다. 여기에 값이 없다면 쿼리를 작성할 때 기본값을 사용할 것입니다. 그러나 이것이 진절머리 나는 해결책처럼 보일 것입니다.

답변

8

많은 사람들로 인해 많은 문제가 발생했습니다. 그들의 머리카락을 찢어 버린다. 선택 요소의 value 바인딩을 사용하여 options 바인딩을 사용하는 경우 value 전에 options을 지정해야합니다.

바인딩은 사용 가능한 옵션을 작성한 다음 값 바인딩을 통해 선택한 옵션과보기 모델 값이 동기화되도록합니다. 순서를 잘못 지정하면 value 바인딩이 먼저 실행되고 일치하는 옵션을 선택할 수 없으므로 값을 null로 설정합니다.

여기 순서와 바이올린이 전환입니다 : http://jsfiddle.net/rniemeyer/32fYk/

이 github에 몇 번에 기록 된, 가장 최근에 여기 : https://github.com/SteveSanderson/knockout/issues/58. 현재 바인딩은 동일한 데이터 바인딩에서 다른 바인딩보다 먼저 실행되도록하는 간단한 방법은 없습니다. 다행스럽게도, 어느 시점에서 이것이 다루어 질 것입니다. 두 바인딩이 다른 하나가 나열되어 있는지 확인하여이 경우를 특별히 처리 할 수있는 픽스를 생각해 볼 수 있습니다.

+1

정말 고마워요! 이것은 아름답게 작동합니다. 내 유일한 문제는 여전히 입력 요소에 대한 제약 조건 데이터 바인딩에 문제가 적용되는 것 같지만 빈 입력 값이 없어야하므로이 작업은 간단합니다. 이제 항목을 제거하는 기능을 추가하십시오 ... 기록을 위해 귀하의 블로그는 대부분의 Google 검색에서 많은 부분을 읽었습니다. 거의 모든 것을 읽은 지난 몇 시간을 보냈습니다. – daedalus28

+4

JSON에 직렬화 할 때 값이 null 인 속성은 무시되므로 Filter ('this.criteria = ko.observable (' '))에 대한 생성자 함수에서 빈 문자열에'criteria'를 강제로 입력 요소를 수정할 수 있습니다. ;)') –

+1

고마워, 그뿐 아니라 잘 :) – daedalus28

관련 문제