2010-12-13 4 views
5

Ich erstelle eine App mit der sehr knockout KnockoutJS-Bibliothek, aber ich habe einen Haken gefunden. Auf der HTML-Seite habe ich ein einfaches <select> Steuerelement, das ich mit JSON-Daten laden möchte, die von einem Webdienst zurückgegeben werden.ObservableArray nicht widerspiegeln Datenaktualisierung

I definieren die beobachtbaren Array wie folgt:

var laborRow = function() { 
    this.positions = ko.observableArray([]); 
}; 

Wenn die Seite geladen wird, wird der Anruf getätigt ajax und die Daten zurückgegeben werden. In der Callback, muss ich folgendes:

success: function (msg) { 
     laborRow.positions = msg; 
    } 

basierend auf den KO docs, ich würde erwarten, dass ich das Ergebnis wie folgt gesetzt werden würde:

laborRow.positions(msg); 

jedoch, dass nur einen Fehler wirft die besagt, dass "laborRow.positions in nicht eine Funktion"

die Vorlage im HTML ist wie folgt:

<tbody data-bind='template: {name: "laborRowTemplate", foreach: laborLine}'> </tbody> 
</div> 
    <script type="text/html" id="laborRowTemplate"> 
     <tr> 

      <td><select data-bind='options: positions, optionsText: "Title", optionsCaption: "select", value: selectedPosition '></select></td> 

     </tr> 
    </script> 

Das Objekt laborRow ist eine Eigenschaft im ViewModel, die an die Seite gebunden ist. Aus irgendeinem Grund funktioniert das nicht. Um eine weitere Falte hinzuzufügen, wenn ich Code hinzufüge, um in das ObservableArray zu schauen und ein Stück Daten auszudrucken, sind die Daten dort drin. So wird es erfolgreich geladen.

Alle Gedanken würden sehr geschätzt werden.

Der vollständige Code für meinen Beispielfall:

var laborRow = function() { 
    this.positions = ko.observableArray([]);  
}; 

var projectEstimate = function() { 
    this.laborLine = ko.observableArray([new laborRow()]); 

}; 

var projectViewModel = new projectEstimate(); 
ko.applyBindings(projectViewModel); 

//and the code in the callback function on ajax success 

success: function (msg) { 
       laborRow.positions = msg; 
       //laborRow.positions(msg); **this does not work - error is laborRow.positions is not a function** 
      }, 

und die HTML-:

<tbody data-bind='template: {name: "laborRowTemplate", foreach: 
laborLine}'> </tbody> 

    <script type="text/html" id="laborRowTemplate"> 
     <tr> 
      <td><select data-bind='options: positions, optionsText: 
"Title", optionsCaption: "select", value: selectedPosition '></ 
select></td> 

     </tr> 
    </script> 

Schließlich dank Seans Kommentare unten, konnte ich es in durch Modifizieren des Code zum Laufen bringen der Rückruf lautet wie folgt:

Antwort

5

Das Problem ist, dass Sie Ihr Modell nicht tatsächlich erstellt haben:

var laborRow = function() { 
    this.positions = ko.observableArray([]); 
    // will only be called if you call var some_var = new laborRow() 
}; 

Ändern Sie Ihre Funktion zu einem bloßen Objekt (wie in der Knockout docs dargestellt):

var laborRow = { 
    positions: ko.observableArray([]) 
}; 

Und Sie werden in der Lage sein laborRow.positions(msg); anrufen und haben es funktionieren.


EDIT

Basierend auf den neuen Code wird laborRow noch nicht instanziiert - wenn Sie var laborRow woanders in Ihrem Code setzen (um den Ajax-Request, vielleicht), dann werden Sie wollen um sicherzustellen, dass Ihr Call-Stack wie folgt aussieht:

projectViewModel.laborLine()[0].positions() 
// This will return the array you're looking for. 
// The key is that laborLine is a `getter` not an attribute 

ich habe durch die „ko-Variablen sind getters nicht attributes“ Fehler mehrmals gebissen worden ... könnte das mit deinem Code passieren?

+0

Danke für die Antwort Sean. Ich habe das Modell erstellt. Im tatsächlichen viewModel habe ich ein observableArray, das bei seiner Erstellung mit einem neuen laborRow-Objekt als solches beginnt: this.laborLine = ko.observableArray ([new laborRow()]); – Alex

+0

@Alex - ausgezeichnet ... könnten Sie dann ein wenig mehr von Ihrem Code posten? Wie du es gerade beschreibst * sollte * funktionieren *. –

+0

@Alex - aktualisierte Antwort, um einen weiteren Stich zu machen. –