2014-04-22 3 views
1

녹아웃 매핑 플러그인을 사용하여 관찰 가능 어레이의 항목에 계산 된 속성을 추가하고 있습니다. 그러나이 계산 된 속성은 내 viewmodel의 다른 속성에 의존합니다.녹아웃 매핑 플러그인에서 viewmodel에 액세스

매핑하는 동안 관찰 가능을 만들 때 viewmodel 속성에 액세스하려면 어떻게해야합니까?

viewModel에서 속성이 더 올라 가기 때문에 options.parent를 사용할 수 없습니다.

서버 측에서 생성 되었기 때문에 viewmodel도 변경할 수 없습니다.

편집 :

다음은 문제를 보여주는 JSFiddle입니다. 주석 처리 된 줄은 내가 일하기 위해 필요한 것입니다.

http://jsfiddle.net/g46mt/2/

이 내가 지금 무엇을, 그러나 분명히 오류를 던지고있다 :

var mapping = { 
    'Collection': { 
     create: function(options) { 
      var model = ko.mapping.fromJS(options.data); 
      model.Total = ko.computed(function() { 
       var result = this.Price() * viewModel.Count(); // :(
       return result; 
      }, model); 

      return model; 
     } 
    } 
}; 

var json = { ... large json object ... }; 
var viewModel = ko.mapping.fromJS(json, mapping); 
+2

적어도 json 구조의 관련 부분을 게시하십시오. 우리는 최소한 Collection의 위치와 Price와 Count 속성이 필요하며 어디에서 'Total' proeprty를 갖고 싶습니까? – nemesv

+0

질문은 특정 json 구조가 아니기 때문에 json이 적절하다고 생각하지 않았습니다. 하지만 문제를 보여주는 JSFiddle 작업을 추가했습니다. – SaphuA

답변

1

한 가지 가능한 해결책은 {deferEvaluation: true} 옵션을 사용하는 것입니다. viewModel가 준비되면 그래서 계산 기능은 평가 될 것입니다 귀하의 Total 속성은 실제로 사용됩니다

var mapping = { 
    'Collection': { 
     create: function(options) { 
      var model = ko.mapping.fromJS(options.data); 
      model.Total = ko.computed(function() { 
       var result = this.Price() * viewModel.Count(); 
       return result; 
      }, model, {deferEvaluation: true}); 
      return model; 
     } 
    } 
}; 

데모 JSFiddle합니다.

그러나이 방법을 사용하면보기 모델 이름을 매핑 옵션과 밀접하게 결합 할 수 있습니다. var viewModel = ko.mapping.fromJS(json, mapping);을 변경하고 viewModel의 이름을 다르게 지정하면 매핑 구성을 업데이트해야합니다. 여기

는 다른 접근 방식은 필기 viewmodels를 사용하여 아래로 통과

아마 매핑 플러그인이 최선의 해결책이 아니라이 시나리오에 대한 매핑 설정의 "부모"체인을 걸을 수있는 방법이 없기 때문에 ... "루트"는 어디에 필요합니까 :

var MainViewModel = function (json) {  
    ko.mapping.fromJS(json, { 'ignore': ["Foo"] }, this); //map the rest 
    this.Foo = new FooViewModel(json.Foo, this); 
} 

var FooViewModel = function (json, root) { 
    ko.mapping.fromJS(json, { 'ignore': ["Bar"] }, this); //map the rest 
    this.Bar = new BarViewModel(json.Bar, root); 
} 

var BarViewModel = function (json, root) { 
    ko.mapping.fromJS(json, { 'ignore': ["Collection"] }, this); //map the rest 
    this.Collection = ko.mapping.fromJS(json.Collection, { 
     create: function(options) { 
      var model = ko.mapping.fromJS(options.data); 
      model.Total = ko.computed(function() { 
       var result = this.Price() * root.Count(); 
       return result; 
      }, model); 

      return model; 

     }}); 
} 

데모 JSFiddle.

1

매핑 플러그인을 사용하면 여러 소스에서 매핑 할 수 있습니다. 제 생각에는 당신이 할 수있을 것 같아요

var viewModel = ko.mapping.fromJS(json); 
viewModel = ko.mapping.fromJS(json, mapping, viewModel), 

첫 번째 매핑 후, 각 가격이있는 콜렉션이 관찰 가능으로 있습니다. 두 번째 매핑 후에는 관측 가능뿐만 아니라 총계를가집니다.

demo i jsfiddle

+0

그래,하지만이 솔루션은 전체'json' 구조체를 두 번 거쳐야하며 매핑 설정에서'viewModel' 변수 이름을 갖는 문제도 해결되지 않습니다 ... – nemesv

+0

@nemesv 구조체를 두 번 걷는 것에 대해 알고 있습니다. 두 번째 해결 방법이 마음에 들었습니다.이를 방지합니다. 'viewModel' 변수 이름은 제 의견으로는 걱정할 필요가 없습니다. json 구조의 Count 변수가 이름을 변경하면 어떻게 될까요? 저에게 매핑 구성의 equal 종속성이 있습니다. –

+0

'Count'와 사실상 'Price'는 서로 다른 종속성입니다. JSON 구조가 변경 될 때만 변경해야하며이를 피할 방법이 없습니다. 계약/인터페이스가 변경되면 양쪽 끝을 변경해야합니다. 그러나 'viewModel'은 독립적으로 변경할 수있는 변수의 이름에 대해 다른 종속성을 가지며 종속성이 있음을 인식하지 못합니다. 간단한 리팩토링 (로컬 변수 이름 바꾸기)을하면 완전히 관련이없는 장소에서 코드를 깨뜨릴 수 있다는 것은 매우 위험합니다. – nemesv