2016-11-12 1 views
0

J'ai un modèle KO avec beaucoup d'objets imbriqués et des collections d'objets imbriqués. J'utilise les options de mappage ko.mappings pour m'assurer qu'elles sont correctement générées lors de la création du modèle, mais la valeur est effacée. Essayer de commencer par une simple goutte vers le bas des objets de menu et de se lier à elle:Mappage Knockout: Pourquoi les liaisons d'application effacent-elles les valeurs de mes objets imbriqués?

<select id="myList" name="SelectedSurvey" id="SelectedSurvey" class="form-control" 
data-bind="options: AvailableSurveys, optionsText: 'Name', value: SelectedSurvey, 
optionsCaption: '-- Select Survey --'"></select> 

Ensuite, prendre des données, lors de la création d'un nouvel objet sur la page, il fonctionne très bien, mais en essayant de modifier un enregistrement existant de la même page, la valeur déroulante n'est jamais sélectionnée. Lorsque je vérifie viewModel.SelectedSurvey() the value is undefined, but it only becomes undefined after I call applyBindings() `. Pourquoi cela arrive-t-il? Comment puis-je le réparer?

Voici un exemple de travail: http://jsfiddle.net/6wLcr52y/3/

Si vous ouvrez la console et l'exécuter, vous verrez le journal avant applyBindings() est appelé la pleine ViewModel, et l'objet imbriqué SelectedSurvey() sont komapping correctement des objets qui ont des valeurs , mais après c'est appelé. SelectedSurvey() devient indéfini et en tant que tel ma liste déroulante n'a jamais une valeur sélectionnée.

Répondre

0

Le paramètre SelectedValue ne semble pas vouloir accepter un objet comme valeur valide. Il efface donc la valeur SelectedValue observable dès que vous appliquez des liaisons en pensant qu'aucune valeur valide n'a été fournie.

Pour contourner ce problème, j'ai créé une solution qui utilise le paramètre optionsValue pour accepter la propriété 'Id' comme valeur. Cela vous permettra de garder le contrôle sur l'enquête sélectionnée en transmettant simplement une valeur "Id" par opposition à un objet Survey complet.

Cela nécessite la mise à jour de votre version Knockout vers la version 3.4.0. Êtes-vous bloqué pour utiliser 2.2.1 pour une raison quelconque?

J'ai également mis à jour votre jsfiddle pour inclure une implémentation plus lisible du plugin de mapping. Espérons que cela va résoudre votre problème:

var ViewModel = function(data) { 
    var self = this; 
    self.AvailableSurveys = ko.mapping.fromJS(data.AvailableSurveys); 
    self.SelectedId = ko.observable(data.SelectedSurvey.Id); 
    self.SelectedSurvey = ko.pureComputed(function() { 
     for (i = 0; i < self.AvailableSurveys().length; i++) { 
      if (self.AvailableSurveys()[i].Id() === self.SelectedId()) { 
       return self.AvailableSurveys()[i]; 
      } 
     } 
    }) 
} 

Fiddle:http://jsfiddle.net/dw1284/v1L5tw6h/3/

+0

Cela fonctionne, mais je suis tout à fait frustré par la façon dont ko/œuvres ko.mapping. Pourquoi existe-t-il une différence entre créer et éditer des fonctionnalités, que vous fournissiez ou non quelque chose avec une valeur? J'ai ce problème chaque fois qu'il y a un objet imbriqué ou une collection imbriquée d'objets en essayant de l'initialiser. Par exemple, vérifiez ce violon: http://jsfiddle.net/6wLcr52y/6/ La méthode d'abonnement, il ne mettra pas le selectedSurvey en charge, mais si vous l'avez choisi en changeant la liste déroulante, cela fonctionne bien et définit l'ensemble objet. – SventoryMang

+0

Je suppose que je devrais demander des éclaircissements sur quand utiliser le plugin de mapping vs pas, parce que vous utilisez à la fois observable simple et le ko.mapping.fromJS. Je pense que cette partie me gâche. Dans mon expérience normale, lorsque vous travaillez avec des objets imbriqués, et en leur attachant une méthode d'abonnement, lors de la modification de l'enregistrement, j'obtiendrais un message d'erreur "SelectedSurvey n'est pas une fonction". Si un objet imbriqué était souscrit comme dans mon violon original. Je pensais que c'était parce que le plugin de mapping ne l'enveloppait pas assez et que chaque propriété devait être une propriété de mapping (en l'enveloppant de manière à avoir une propriété ko_mapping_). – SventoryMang

+0

La seule fois où vous auriez besoin d'utiliser le plugin de mapping, c'est quand vous avez besoin que les propriétés enfant soient elles-mêmes observables. Par exemple, si vous avez l'intention de mettre à jour les noms de Survey à la volée, et que vous souhaitez que ces noms mis à jour soient reflétés dans l'interface graphique, vous aurez besoin du plugin de mapping pour générer votre objet self.AvailableSurveys. La raison pour laquelle j'ai utilisé une simple observable pour la propriété self.SelectedId est que le champ Id n'a aucun enfant à convertir en observables, il est donc inutile d'utiliser le plugin de mapping sur celui-ci. –