2010-12-13 4 views
5

Je suis en train de créer une application en utilisant la bibliothèque KnockoutJS, mais j'ai rencontré des problèmes. Sur la page html, j'ai un contrôle simple <select> que je veux charger avec des données JSON retournées par un service Web.ObservableArray ne reflétant pas la mise à jour des données

Je définissiez le tableau observable comme suit:

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

Lorsque la page se charge, l'appel ajax est faite et les données sont renvoyées. Dans le rappel, je fais ce qui suit:

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

sur la base des documents KO, je me attends que je mettrais le résultat comme celui-ci:

laborRow.positions(msg); 

Cependant, cela jette juste une erreur indiquant que "laborRow.positions dans pas une fonction"

le modèle dans le code HTML est comme suit:

<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> 

L'objet laborRow est une propriété du ViewModel lié à la page. Pour une raison quelconque, cela ne fonctionne pas. Pour ajouter une autre ride, si j'ajoute du code pour jeter un œil dans observableArray et imprimer un morceau de données, les données sont là. Donc, il est chargé avec succès.

Toutes les pensées seraient grandement appréciées.

Le code complet pour mon exemple le cas:

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** 
      }, 

Et le code 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> 

Enfin, grâce aux commentaires de Sean ci-dessous, j'ai pu le faire fonctionner en modifiant le code le rappel comme suit:

success: function (msg) { 
    projectViewModel.laborLine()[(projectViewModel.laborLine().length-1)].positionList(msg); 
} 

Répondre

5

Le problème est que vous n'avez pas créé votre modèle:

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

Changer votre fonction à un objet nu (comme le montre le Knockout docs):

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

Et vous serez en mesure d'appeler laborRow.positions(msg); et de le faire fonctionner.


EDIT

Basé sur le nouveau code, laborRow est toujours pas instancié - si vous mettez var laborRow ailleurs dans votre code (autour de la demande de paiement ajax, peut-être), alors vous aurez envie pour vous assurer que votre pile d'appel ressemble à ceci:

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

J'ai été mordu par les « variables ko sont getters pas attributes » bug à plusieurs reprises ... cela pourrait-il arriver avec votre code?

+0

Merci pour la réponse Sean. J'ai créé le modèle. Dans le viewModel actuel, j'ai un observableArray qui, lorsqu'il est créé, commence la vie avec un nouvel objet LaborRow en tant que tel: this.laborLine = ko.observableArray ([new laborRow()]); – Alex

+0

@Alex - excellent ... pourriez-vous poster un peu plus de votre code alors? Comme vous le décrivez, tout devrait fonctionner. –

+0

@Alex - réponse mise à jour pour faire un autre coup de poignard. –

Questions connexes