2017-07-09 1 views
1

J'ai transmis un modèle à mon View Model de .Net, qui est un objet, contenant quelques champs, et une liste, et chacun d'eux a une autre liste.Array Observable Array of Array Observable

Donc, un objet avec une liste de listes.

Sur ma vue, je représente ceci comme des données, avec une liste d'onglets (la première liste), puis chaque onglet a une grille de données.

Dans mon modèle Voir knock-out, je viens de:

self.Name = ko.observable(""); 
self.Width = ko.observable(0); 
self.Height = ko.observable(0); 

self.TemplateGroups = ko.observableArray(); 

Alors, mon objet principal, avec un tableau observable (la première liste). Mais, la liste à l'intérieur de cela, n'est pas observable.

Ainsi lors du rendu mes tabls, je fais:

<div class="tab-content" data-bind="foreach: TemplateGroups"> 

Et qui rend chaque onglet. Et puis dans chaque onglet, je fais ceci: Je suis

<tbody data-bind="foreach: $data.Components"> 
     <tr style="cursor: pointer" data-bind="click: $parents[1].ClickedIt"> 

(« composants » est le nom de la liste dans la liste extérieure)

Le problème est, sur ma fonction ClickIt, l'affichage de la Idof la J'ai cliqué sur la ligne, et cela fonctionne. Et puis, je suis juste en train de changer le champ « Description » de cette liste extérieure, mais ... ce n'est pas une fonction, donc, non observé:

self.ClickedIt = function() { 
    alert(this.Id); 
    this.Description("Craig"); 

} 

L'alerte indique l'identification, mais l'erreur sur Description ("Craig"), car ce n'est pas une fonction.

Comment puis-je rendre la liste, dans mon ObservableArray, observable?

(Pour être plus clair, mon modèle passe est un objet qui contient une liste appelée TemplateGroups ... puis chaque élément de cette liste contient une liste appelée 'Components'. Les composants que j'affiche, mais je dois rendre cette liste Observable

Edit: Cela semble être ce que je cherche (http://jsfiddle.net/rniemeyer/bZhCk/), mais ... Je ne définis pas mon tableau de la même façon. ils sont passés d'une classe .Net (donc, convertie en JSON, je pense) et cette classe .Net contient une liste d'une autre classe .Net, qui a une liste).

Remarque, Ma méthode de charge:

self.loadData = function() { 
     $.get("/api/PlateTemplate/Get", { id: self.TemplateId() }).done(function (data) { 
      self.Name(data.Description); 
      self.Width(data.Width); 
      self.Height(data.Height); 
      self.TemplateGroups(data.PlateTemplateGroups); 
     }); 
    } 
+1

Le contenu de 'self.TemplateGroups' ne sont pas observables.Ce sont des objets javascript simples. Peut-être pourriez-vous utiliser le Plugin Mapping (http://knockoutjs.com/documentation/plugins-mapping.html): 'self.TemplateGroups (ko.mapping.fromJS (data.PlateTemplateGroups));', dans votre 'self.loadData '. De cette façon, toutes les propriétés deviennent observables. –

+0

@JoseLuis - Parfait! Wow, merci beaucoup! Cela a fonctionné parfaitement. Lorsque je souhaite renvoyer mes données de modèle de vue à la même structure, existe-t-il un moyen de mapper le modèle de vue à la structure dans laquelle je l'ai reçu, avec les valeurs mises à jour? Donc, comme un «toJSON», ou quelque chose? aussi, si vous pouvez créer une réponse, et je peux l'accepter. Merci! (encore!) – Craig

Répondre

1

Le contenu de self.TemplateGroups est data.PlateTemplateGroups, qui est un tableau et son contenu ne sont pas des propriétés observables (ils sont des objets javascript).

Si vous voulez que ces objets dans ce tableau deviennent observables, vous pouvez utiliser le Mapping Plugin:

self.loadData = function() { 
    $.get("/api/PlateTemplate/Get", { id: self.TemplateId() }).done(function (data) { 
     self.Name(data.Description); 
     self.Width(data.Width); 
     self.Height(data.Height); 
     self.TemplateGroups(
      ko.mapping.fromJS( // <--- new 
      data.PlateTemplateGrou‌​ps)); 
    }); 
} 

De cette façon, toutes les propriétés deviennent observables.

Si vous avez besoin de convertir ces données en un format JSON vous pouvez utiliser ko.mapping.toJS():

ko.mapping.toJS(self.TemplateGroups) 
+0

Merci @JoseLuis - Sauver en arrière semble être un problème cependant. Est-ce aussi simple que d'utiliser ko.mapping.toJS (self) pour renvoyer toutes les données du modèle de vue, y compris la liste et la liste de liste, à ma fonction WebAPI, dans le même format que celui qui a été transmis au modèle de vue ? Ou dois-je faire un peu plus? Comme j'obtiens des erreurs quand j'essaie la méthode toJS. Il se bat avec mes clics/enregistrer des fonctions. – Craig

+0

@Craig Je ne sais pas, quand j'envoie un JSON, je fais ceci: 'var unmapped = ko.mapping.toJS (self); var unmappedJSON = ko.toJSON (non mappé); 'Ce code entre dans une fonction de mon ViewModel, à cause de cela j'utilise' self'. –

+0

Ceci est un exemple: https://codepen.io/anon/pen/QgzqVe –