2013-05-03 23 views
0

我想做一個基於敲除的應用程序,我遇到了一個看似不能解決的問題:我正在製作一個用於操作事件對象列表的UI。事件對象列表顯示在主視圖中,其中包含一個事件對象表,其中包含一些可在主視圖中更改的屬性。Knockout.js:改變數組元素的問題

但是,因爲事件對象將包含複雜數據,如子數組等,我希望能夠從事件對象列表中打開模式視圖,以便對單個事件對象進行詳細編輯。模態視圖與主視圖在同一頁面內運行,因此我可以爲兩個視圖使用相同的數據模型。

我能夠在模態視圖中的單個事件對象中編輯屬性,但由於某些原因,這些更改未反映在主視圖中。當我迭代事件數組時,我可以看到有問題的數組元素已被更改。我嘗試在數組(這是一個可觀察數組)上執行valueHasMutated方法,但這沒有效果。希望這裏有一些好的建議。我試着編譯一個自包含的HTML頁面,它比單詞更好地解釋了這個問題。但是恐怕代碼有點長。但在這裏它是無論如何: 淘汰賽測試

<form id="photograph-form"> 
    <div class="row-fluid span12"> 
     <h4>Events</h4> 
     <table class="table table-condensed table-hover span11 table-striped"> 
      <thead> 
      <tr> 
       <th class="span1">Delete</th><th class="span1">Edit</th><th class="span1">Type</th><th class="span1">Dating basis</th> 
      </tr> 
      </thead> 
      <!-- Todo: Generate table body --> 
      <tbody data-bind="foreach: events"> 
      <tr> 
       <td><a href="#" data-bind="click: $root.removeEvent"><i 
         class="icon-trash"></i></a></td> 
       <td><a data-bind="click: $root.setCurrentEvent" href="#eventView" role="button" 
         data-toggle="modal"> 
        <i class="icon-edit"></i></a></td> 

       <td><select class="input-medium" data-bind="value: event_type, 
            options: event_types, 
            optionsValue: 'identifier', 
            optionsText: 'name'"></select></td> 
       <td><input class="input-medium" data-bind="value: foundation"/> 
       </td> 
      </tr> 
      </tbody> 
     </table> 
    </div> 
</form> 
<p>Current item foundation: <span data-bind="text: currentEvent().foundation"></span></p> 

<div class="row-fluid"> 
    <!-- Button to trigger modal --> 
    <a role="button" class="btn" data-toggle="modal" href="#eventView" data-bind="click: $root.addEvent">New</a> 
</div> 

<!-- Modal window --> 
<div id="eventView" class="modal hide fade" tabindex="-1" role="dialog" 
    aria-labelledby="eventLabel" aria-hidden="true"> 
    <div class="modal-header"> 
     <button type="button" class="close" data-dismiss="modal" 
       aria-hidden="true">× 
     </button> 
     <h3 id="eventLabel">Event</h3> 
    </div> 
    <div class="modal-body"> 
     <label for="eventType">Event type</label> 

     <select id="eventType" class="input-medium" data-bind="value: currentEvent().event_type, 
            options: event_types, 
            optionsValue: 'identifier', 
            optionsText: 'name'"></select> 
     <label for="eventFoundation">Dating basis</label> 
     <input id="eventFoundation" class="input-medium" 
       data-bind="value: currentEvent().foundation"/> 

    </div> 
    <div class="modal-footer"> 
     <button class="btn btn-primary" data-dismiss="modal" 
       aria-hidden="true" data-bind="click: $root.updateEvent">OK 
     </button> 
    </div> 
</div> 

<script src="js/jquery.js"></script> 
<script src="js/bootstrap.min.js"></script> 
<script src="js/knockout.js"></script> 

<script> 
    var event_types = [ 
     { identifier: "accession", name: "Accession" }, 
     { identifier: "other", name: "Other" }, 
     { identifier: "ownership", name: "Ownership" } 
    ]; 

    var model = new ArtifactModel("photograph"); 
    model.history_description = ko.observable(); 
    model.events = ko.observableArray([ 
     { event_type: "accession", foundation: "Found"}, 
     { event_type: "ownership", foundation: "Museum"} 
    ]); 
    model.currentEvent = ko.observable({ event_type: "accession", foundation: "Found"}); 

    ko.applyBindings(model); 


    function ArtifactModel(artifact_type) { 
     var self = this; 
     self.artifact_id = ko.observable(); 
     self.events = ko.observableArray(); 
     self.currentEvent = ko.observable(); 

     // Operations 
     self.addEvent = function() { 
      self.events.push({ 
       event_type: "", 
       foundation: "" 
      }); 
      self.currentEvent(self.events()[self.events().length - 1]); 
     }; 

     self.setCurrentEvent = function(event) { 
      self.currentEvent(event); 
      console.log("Before: Event.foundation: " + self.currentEvent().foundation); 
     }; 

     self.updateEvent = function(event) { 
      for (var t = 0 ; t < event.events().length ; t++) { 
       console.log("After: Event.foundation: " + event.events()[t].foundation); 
      } 
      event.events.valueHasMutated(); // No effect! 
     } 
    } 
</script> 
</body> 
</html> 

回答

0

這個問題可能是因爲你的event對象沒有可觀察的屬性本身。嘗試改變事件定義是這樣的:

{ 
    event_type: ko.observable("accession"), 
    foundation: ko.observable("Found") 
} 

您可能需要進行一些其他更改佔的事實,這些屬性現在觀察到的,但是這將意味着變化從一個位置到對象進行將反映在其他地點。

+0

的潛在問題與此解決方案您的演示,是模型和事件陣列將首先使用Ajax來填充。我不確定是否有可能強加可觀察的財產。但我會試一試。謝謝! – 2013-05-06 07:54:07

+0

建議的解決方案有效:編輯通過UI添加的事件時,使屬性可觀察。 至於由ajax調用產生的事件,似乎ko.mapping.fromJS方法自動將屬性設置爲可觀察的。 – 2013-05-06 08:28:48

0

你需要擁有的是具有可觀察值的對象數組。那麼你不需要做任何額外的事情。

這將是有益的,如果你將不得不在http://jsfiddle.net/

+0

我只在http://jsfiddle.net/VhJ36/上有一個演示。 – 2013-05-06 07:49:19