2012-11-07 3 views
2

knockout 템플릿에서 전체 observable 데이터 컨텍스트에 액세스해야합니다.knockoutjs 템플릿 내에서 데이터 컨텍스트의 관찰 가능에 액세스하는 방법

개발중인 응용 프로그램에서 일반적으로 뷰를 일반적으로 렌더링하는 데 사용하는 많은 메타 데이터가 있습니다.

ViewModel.AwesomeProperty = { 
    value: ko.observable('Awesome Value'), 
    label: 'My Awesome Label', 
    template: 'awesomeTemplate', 
    otherMetaData: 'etc' 
} 

나는 특성이 될이 메타 데이터를 변경 해요 : (값 속성에 값) 메타 데이터 및 서브 속성으로 데이터를 모두 저장 - 과거에 내가보기 모델 속성 단지를했습니다 (Ryan Niemeyer가 자신의 블로그 게시물이나 세션 중 하나에서 설명한 것처럼). 나는 그것이 더 깨끗하고, 더 우아하고, 일반적으로 오버 헤드가 적어 유지 보수가 용이하다는 것을 발견했다. (특히 직렬화의 경우).

ViewModel.AwesomeProperty = ko.observable('Awesome Value'); 
ViewModel.AwesomeProperty.label = 'My Awesome Label'; 
ViewModel.AwesomeProperty.template = 'awesomeTemplate'; 
ViewModel.AwesomeProperty.otherMetaData = 'etc'; 

이렇게 부작용이 템플릿 ViewModel.AwesomeProperty 통과하면,이 경우의 관찰 값을 데이터 컨텍스트 (설정이다 '최고 값을 다음과 같이 상기 실시 예에 상응하는 것 '), $ 데이터에서 액세스 할 메타 데이터 제작 :

<script id="example" type="text/html"> 
    <!-- This won't work anymore --> 
    <span data-bind="text: $data.label></span> 
</script> 
<div data-bind="template: {name: 'example', data: AwesomeProperty}"></div> 

지금과 같이 익명 객체의 데이터 값을 래핑하는 것입니다 가지고있는 해결 방법 :

<script id="example" type="text/html"> 
    <!-- Now it works again --> 
    <span data-bind="text: data.label></span> 
</script> 
<div data-bind="template: {name: 'example', data: {data:AwesomeProperty}}"></div> 

그러나 이것은 우아하고 이상하지 않습니다. 자동 생성이 많이 필요한 경우 이는 불편할뿐만 아니라 실제로 주요한 장애물입니다. 나는 템플릿 바인딩을 감싸는 커스텀 바인딩을 만드는 것을 고려해 봤지만 더 나은 솔루션이 있기를 바라고있다.

다음은 계단식 드롭 다운을 위해 작업해온 실제 사례입니다. This JSFiddle이 작동하지만 that JSFiddle 않습니다. 사전에

감사합니다.

답변

1

knockout은 언 래핑 된 값을 항상 사용합니다. 그런 일이 관측 가능하다면 하위 속성을 잃을 것입니다. 관측 대상을 다른 대상으로 다시 감싸서 이미 발견 한대로 잃지 않도록해야합니다.

이것을 마무리 할 수있는 좋은 방법은이 재 포장을 수행 할 구독 가능 항목 (또는 더 많은 파생 된 유형)에 대한 함수를 만드는 것입니다. 이 재 포장 된 객체에 모든 개별 메타 데이터를 집어 넣거나 개별 객체에 포장 할 수 있습니다. 코드가 다시 우아해질 수 있습니다.

var buildSelection = function (choices, Parent) { 
    return _(ko.observable()).extend({ 
     // add the metadata to a 'meta' object 
     meta: { 
      choices: choices, 
      availableChoices: ko.computed(function() { 
       if (!Parent) return choices; 
       if (!Parent()) return []; 
       return _(choices).where({ ParentID: Parent().ID }); 
      }) 
     } 
    }); 
} 

ko.subscribable.fn.templateData = function (metaName) { 
    return { 
     // access the value through 'value' 
     value: this, 
     // access the metadata through 'meta' 
     meta: this[metaName || 'meta'] // meta property may be overridden 
    }; 
} 

바인딩에서이 함수를 호출하여 재 포장 된 객체를 만듭니다. 템플릿에서 바인딩을 조정해야합니다.

<script id="Selection" type="text/html"> 
    <select data-bind=" 
      options: meta.availableChoices, 
      optionsText: 'Value', 
      value: value, 
      optionsCaption: 'Select One', 
      enable: meta.availableChoices().length 
    "></select> 
</script> 

<!-- ko template: { 'name': 'Selection', 'data': Level1.templateData() } --><!-- /ko --> 
<!-- ko template: { 'name': 'Selection', 'data': Level2.templateData() } --><!-- /ko --> 
<!-- ko template: { 'name': 'Selection', 'data': Level3.templateData() } --><!-- /ko --> 

Updated fiddle

관련 문제