2012-12-18 4 views
3

회사에서 제공하는 서비스 (예 : 영업, 서비스, 컨설팅)의 관찰 가능한 배열이 있습니다. 이러한 각 서비스는 미국 내 0 개 이상의 회사에서 수행 할 수 있으며 각 주마다 선택적 인증 번호가 있습니다. 따라서 서비스에는 관찰 가능한 위치 배열이 있으며 위치는 상태 번호와 인증서 번호의 조합입니다.녹아웃 : 관찰 가능한 배열 및 체크 박스와의 복잡한 바인딩

function Service(name) { 
    var self = this; 

    self.Name = ko.observable(name); 
    self.Locations = ko.observableArray(); 
} 

function Location(state) { 
    var self = this; 

    self.State = ko.observable(state); 
    self.CertNum = ko.observable(); 
} 

사용자 인터페이스에서 모든 미국 국가의 단일 목록을 표시하려고합니다. 사용자는 회사가 운영하는 각 주 옆에있는 확인란을 선택하여 상태의 "마스터 목록"을 만듭니다. 이 마스터 목록은 각 가능한 서비스 아래에 나타나는 선택 항목을 차례로 표시합니다.

예를 들어, 사용자는 마스터 목록에서 "Alabama"및 "Arizona"를 틱합니다. 그런 다음 UI는 각 서비스에 대한 별도의 위치를 ​​확인란과 텍스트 상자의 조합으로 렌더링합니다.

function viewModel() { 
    var self = this; 

    self.AllStates = [ 
     { name: "Alabama", abbrev: "AL" }, 
     { name: "Alaska", abbrev: "AK" }, 
     { name: "Arizona", abbrev: "AZ" }, 
     { name: "Arkansas", abbrev: "AR" } 
    ]; 

    self.BusinessStates = ko.observableArray(); 

    self.AllSelectedStates = ko.computed(function() { 
     return ko.utils.arrayFilter(self.AllStates, function(item) { 
      return self.BusinessStates.indexOf(item.abbrev) >= 0; 
     }); 
    }); 

    self.Services = ko.observableArray([ 
     new Service("Sales"), 
     new Service("Service"), 
     new Service("Consulting") 
    ]); 
} 

간단한보기과 같습니다 : 여기에 마스터 뷰 모델의 적어도 볼

<h2>Master List</h2> 
<ul data-bind="foreach: AllStates"> 
    <li> 
     <label><input type="checkbox" data-bind="value: abbrev, checked: $root.BusinessStates"/> <span data-bind="text: name"></span></label></li> 
</ul> 

<h2>Services</h2> 
<div class="service" data-bind="foreach: Services"> 
    <h3 data-bind="text: Name"></h3> 
    <ul data-bind="foreach: $root.AllSelectedStates"> 
     <li> 
      <label> 
      <input type="checkbox" data-bind="value: abbrev, checked: $parent.Locations" /> 
      <span data-bind="text: name"></span> 
      </label> 
      <input type="text" placeholder="Cert. Number" data-bind="value: ??" /> 
     </li> 
    </ul> 
</div> 

이 상태는 서비스의 위치 배열로 입력 저를 얻을,하지만 난 방법을 모르는 CertNum 속성을 바인딩합니다.

사용자가 마스터 목록에서 알라바마와 애리조나를 선택했다고 가정 해 보겠습니다. 이제 "판매"서비스의 경우 사용자는 "Arizona"를 선택하고 "98765"라는 인증 번호를 입력합니다. "Consulting"서비스에서 사용자는 "Alabama"를 틱하고 인증서 번호를 입력하지 않습니다. 이상적으로 나는처럼 보이게 결과 JSON 조각을 싶습니다

"Services": [ 
    { 
     "Name": "Sales", 
     "Locations": [ 
      { 
       "State": { "name": "Arizona", "abbrev": "AZ" }, 
       "CertNum": "98765" 
      } 
     ] 
    }, 
    { 
     "Name": "Service", 
     "Locations": [] 
    }, 
    { 
     "Name": "Consulting", 
     "Locations": [ 
      { 
       "State": { "name": "Alabama", "abbrev": "AL" }, 
       "CertNum": null 
      } 
     ] 
    } 
] 

내가 렌더링 및 미국 국가의 "마스터 목록"을 바인딩 할 수 있습니다. 서비스를 반복하고 사용 가능한 각 서비스 위치 (즉, 상태의 체크 박스, 인증서 번호의 텍스트 상자)에 대한 컨트롤을 제공하는 UI를 렌더링 할 수 있습니다. 내가 할 수 없었던 것은 서비스 위치 컨트롤을 바인드하여 해당 위치 배열의 위치 멤버십을 제어하고 동시에 인증 번호의 값에 영향을 미칩니다.

제가 만든 가장 근접한 시도는 매우 복잡하고 해키입니다. 여기서는 knockout-postBox plugin을 사용하여 viewModel.AllSelectedStates 속성을 각 서비스 모델의 비슷한 속성에 연결 한 다음 각 Service.Locations로 새 위치를 푸시합니다 정렬. 거의이 작동하지만 마스터 목록에서 상태가 선택되거나 선택 취소 될 때마다 서비스의 변경 사항이 지워집니다. 또한 각 서비스의 Locations 배열에 사용 가능한 모든 위치를 푸시하고 위치에 IsSelected 부울 플래그를 사용하여 선택되었는지 확인해야합니다. 그냥을 선택한 배열의 위치로 지정합니다.). http://jsfiddle.net/cbono/PU6Sq/23/

그것에 대해 좋은 점은 그것이 UI의 작동 방법을 보여줍니다입니다 :

는이 JSFiddle의 시도를 볼 수 있습니다. 그러나 postBox 플러그인이 없으면 이것이 가능하다고 생각합니다. 문제를 해결할 올바른 방법을 찾지 않고 있습니다. 나는 이것을 통해 며칠을 보냈으며 100 % 작동하는 해결책을 제시 할 수 없습니다.

답변

0

바인딩 이벤트를 관리하는 것보다 visible 바인딩을 사용하는 것이 더 쉽습니다.당신이 정말로 그들을 처리해야하는 경우

<li data-bind="visible: State().IsSelected"> 

http://jsfiddle.net/MizardX/XTkpb/


, 당신은 Services 객체에 StateAndCert 객체를 캐시 수 :

var self = this, 
    cache = {}; 

self.Locations = ko.computed(function() { 
    return ko.utils.arrayMap(states(), function (item) { 
     var key = item.Abbrev(); 
     if (cache[key] === undefined) { 
      cache[key] = new StateAndCert(item); 
     } 
     return cache[key]; 
    }); 
}); 

http://jsfiddle.net/MizardX/HMAtE/


는 JSON 렌더링에서 특정 속성을 숨기려면, 당신은 function(){} 건물 내부를 채울 수 :

self.Meta = function(){}; 
self.Meta.IsSelected = ko.observable(false); 
+0

감사합니다, 마르쿠스을. 나는 당신의 솔루션을 정확히 사용하지 않았지만 당신이 올바른 길을 찾도록 도왔습니다. 한 모델에서 다른 모델로 관찰 가능한 배열을 보내는 것은 내가 생각하지 못했던 것입니다. 그러나, 전체 States 배열을 보내는 대신, 선택된 상태로만 필터링 된 종속 관찰 가능을 만들었습니다. 매력처럼 일했습니다! – CBono

관련 문제