2015-01-14 2 views
0

녹아웃에 "교차 업데이트"문제가 있습니다. 다음 함수 ('self.applyTagsAllocation')는 이상한 결과를 초래합니다. 3 행 : 'scenetag.sceneID = scene.sceneID;' 'tag.sceneID'와 로컬 scenetag- 변수를 업데이트하고 있습니다. 나는 왜 sceneID가 결코 관찰 할 수 없는지를 이해할 수 없다. . 내 뷰 모델의녹아웃과 교차 업데이트 문제

self.applyTagsAllocation = function (tag) { 
     var scenetag = tag; 
     var scene = self.selectedScene(); 
     scenetag.sceneID = scene.sceneID; 
     scene.sceneTags.push(scenetag); 
}; 

Here'sa 더 완전한 목록은 : 내가 다했기 때문에 '장면'는 sceneTags 배열과 태그 배열을 모두 가지고이 왜

var Tag = function (data) { 
    var self = this; 
    self.ID = data.ID || -1;  
    self.sceneID = data.sceneID; 
    self.text = ko.observable((data.text || 'new').trim()); 
    self.tagType = ko.observable(data.tagType || -1); 
} 

var Scene = function(data){ 
    var self = this; 
    self.sceneID = data.sceneID; 
    self.sceneTags = ko.observableArray(); 

    self.tags = ko.computed({ 
     read: function() { 
      var tags = []; 
      tags.push.apply(tags, self.sceneTags()); 
      return tags; 
     }, 
     write: function (tag) { 
      this.sceneTags.push(tag); 
     }, 
     owner: self 
    }); 
}; 

var ViewModel = function (model){ 
    var self = this; 

    self.selectedScene = ko.observable(); 
    self.sceneTags = ko.observableArray(); 

    self.Scenes = ko.observableArray(
     ko.utils.arrayMap(model, function (item) { 
      return new Scene(item); 
     })); 

    self.sceneTags = ko.computed(function() { 
     var tags = []; 
     ko.utils.arrayForEach(self.Scenes(), function (scene) { 
      tags.push.apply(tags, scene.tags()); 
     }); 
     return tags; 
    }); 


    //Tag is first created with: 
    self.addSceneTag = function (name, type) { 
     if (!type) type = -1; 
     var newtag = new Tag({ 
      ID: -1, 
      sceneID: self.selectedScene().sceneID, 
      text: name,  
      tagType: type 
     }); 

     // already in use? 
     var abort = false; 
     ko.utils.arrayForEach(self.selectedScene().sceneTags(), function (tag) { 
      if (tag.text() === newtag.text()) abort = true; 
     }); 
     if (!abort) self.selectedScene().sceneTags.push(newtag); 
    }; 

    self.applyTagsAllocation = function (tag) { 
     var scenetag = tag; 
     var scene = self.selectedScene(); 
     scenetag.sceneID = scene.sceneID; 
     scene.sceneTags.push(scenetag); 
    }; 
}; 

(당신은 궁금 할 것이다 ..이 예에서는 단순화 내 프로젝트에서 나는 다른 태그 형은이 두 종류의 뷰 모델 범위 내에서 함께 병합)

HTML은

태그는 첫 번째로 설정 :

<input class="taginput" placeholder="&lt;add a tag&gt;" data-bind="textInput: tagname, event: {keyup: $root.inputTag}" /> 

는 다음 태그는 내가의 범위에서 또 다른 '현장'에 추가 할 존재하는 경우«foreach 문 : 태그»:

<span data-bind="visible: sceneID !== null && sceneID !== $root.selectedScene().sceneID, click: function(){$root.applyTagsAllocation($data)};">Add Tag</span> 

여기에 실제의 foreach는 knockout- 내에서 루프와 정렬 가능 (Ryan Niemeyer 출품) :

<div class="tag-list" data-bind="sortable:{template:'tagsTmpl',data:$root.sceneTags"></div> 

무엇이 원인 일 수 있습니까? 힌트와 단서가 높이 평가되었습니다!

고맙습니다!

답변

1

다른 기능을 살펴보십시오. 보기에 당신은 기본적으로이

self.applyTagsAllocation = function (tag) { 
    var scenetag = tag; // scenetag == instance of Tag you passed ($data) 
    var scene = self.selectedScene(); // scene == the selected instance of Tag 
    scenetag.sceneID = scene.sceneID; //!!!! This line says: 
    // 'Make sceneID of this instance = sceneID of the selected instance' 
    scene.sceneTags.push(scenetag); // will fail, you can't write to a simple computed 
}; 

는 그래서 그래, 그것은 지역 변수를>을 업데이트 = 수행하는 self.applyTagsAllocation 기능에 태그,하지만 Tag의 ViewModel에 로컬 변수 점을 $data을 결합하고, 그래서 그것은 객체를 업데이트합니다. 여러분이 (생각한 것처럼) 생각한 것처럼, 객체를 다른 변수에 할당해도 객체가 복제되지 않습니다. 그것은 단지 참고 일뿐입니다.

self.applyTagsAllocation = function (tag) { 
    var scenetag = {}; 
    // clone an object, for whatever strange reason one could have: 
    for (var prop in tag) { 
     scenetag[prop] = tag[prop]; 
    } // now you have a copy of the tag instance you passed [..] rest of function 
}; 

또는 좀 더 논리적하다고 생각하는 것이다 선택으로 태그를 설정하고 싶다면 :

오히려 할
self.selectedScene(tag)을 함수에.

중요 : self.sceneTags을 두 번 할당했으며 두 번째로 계산 된 관찰 가능 항목이었습니다. 계산 된 관측 값 (당신이 밀어 넣는 동안 applyTagsAllocation에있는 동안)을 쓸 수 없다면, 당신은 pureComputed를 필요로합니다.

+0

안녕하세요 @ 티 블리츠! 대답 해 주셔서 감사합니다. 복제에 대한 귀하의 제안은 트릭을 수행하는 것으로 보입니다. 훌륭한. 나는 너무 감사한다! :) –

+0

그냥 다른 접근법을 생각해 냈습니다 : 복제 대신 self.selectedScene()를 제외하고 동일한 속성을 가진 새 Tag 객체를 인스턴스화하기 위해 "tag"를 사용할 수있었습니다. sceneID, could not I? 다음 두 기능을 모두 포함하도록 'self.addSceneTag'를 다시 작성해야합니다. –

+1

@AsleG 당신도 할 수 있습니다. 생성자에서'var Tag = function (data, flag) {self.sceneID = flag === true? data.sceneID || 만약 당신이 생성자에 그것을 포함하고 싶지 않다면, 모든 props로 새로운 태그를 만들 수 있습니다.'var x = new Tag (data);'그리고 나중에'x.sceneID = ''와 같은 sceneID를 재 할당 할 수 있습니다. '또는 당신이 소품'delete x.sceneID'를 모두 제거하기를 원합니까? – Tyblitz