Knockout JS mapping plugin sans données initiales / formulaire vide

Nous utilisons knock-out et le plugin de mappage knock-out pour faciliter la liaison de données dans notre application Web jQTouch. La raison pour laquelle nous utilisons le plugin de mappage, est de pouvoir utiliser knock-out sans avoir besoin de définir ou de changer les modèles de vision manuellement en javascript. Le plugin de mappage fonctionne très bien lorsque vous disposez d'une charge de données initiale à partir de la base de données côté serveur / client.

Le problème que nous avons est que nous avons des écrans / vues qui ont une forme dans laquelle il est possible qu'il n'y ait pas de données initiales. Sans cette donnée initiale, le plugin de mappage ne peut pas "générer" le modèle de vision (ko.mapping.fromJS). Cela signifie que nous devons encore définir nos modèles de vision à la main pour une grande partie de nos points de vue.

Suis-je faux en supposant que ce soit un scénario que le plugin de mappage (devrait)? Je veux dire, cela signifie que le plugin de mappage n'est utilisable que dans des scénarios dans lesquels vous avez toujours une première charge de données.

Quelques options pour vous en plus de gérer manuellement votre modèle de vision. Le plugin de mappage prend en charge un rappel de create qui vous permet de personnaliser la façon dont il est créé. Cela peut être utilisé pour ajouter des propriétés par défaut à un objet, s'ils manquent.

Quelque chose comme ceci: http://jsfiddle.net/rniemeyer/WQGVC/

Une autre alternative consiste à utiliser une liaison qui crée des propriétés manquantes. Il pourrait ressembler à:

 //create an observable if it does not exist and populate it with the input's value ko.bindingHandlers.valueWithInit = { init: function(element, valueAccessor, allBindingsAccessor, data) { var property = valueAccessor(), value = element.value; //create the observable, if it doesn't exist if (!ko.isWriteableObservable(data[property])) { data[property] = ko.observable(); } //populate the observable with the element's value (could be optional) data[property](value); ko.applyBindingsToNode(element, { value: data[property] }); } } 

Vous l'utiliserez comme ceci (vous devez passer la propriété en tant que chaîne, sinon elle sera une erreur):

 <input data-bind="valueWithInit: 'name'" /> 

Exemple ici: http://jsfiddle.net/rniemeyer/JPYLp/

Je pense que la solution à votre problème vient de penser au modèle de vue au mauvais sens. Un modèle de vue n'est pas seulement quelque chose qui délivre des données à la vue, mais aussi un détenteur de place pour soumettre les données.

La façon dont je finis généralement de travailler avec knock-out, je ne finis jamais par envoyer un modèle de vue vide à la vue. Le modèle de vue comporte généralement tous les champs sur lesquels je lier. Bien qu'ils puissent être des chaînes vides, ou des objets initialisés sans valeurs d'affichage, les objets réels restent encore, avec une représentation appropriée de chaque objet dans les champs auxquels je lier.

Vous voudrez peut-être regarder simplement envoyer des objets vides au lieu de rien à la vue.

EDIT: l'exemple est un ASP.NET MVC

Donc, basiquement, je, du côté du serveur, je crée un objet de modèle de vue, qui contient toutes les données qui doivent être affichées ainsi que toutes les données à collecter. Pour faciliter le code de validation, je place généralement les données à collecter dans sa propre sous-classe, mais cela concerne toutes les exigences de votre code.

Dans tous les cas, tout objet allant à la vue est lié à une classe vmBase qui fournit essentiellement une méthode toJSON () qui génère la sérialisation JSON de l'objet. Ceci est appelé à mon avis par le moteur de visualisation. Comme indiqué dans le code ci-dessous.

  <script type='text/javascript'> var viewModel = ko.mapping.fromJS(<%= Model.ToJson() %>); $(document).ready( function () { ko.applyBindings(viewModel); }); </script> 

Lorsque je suis prêt à envoyer le code, je supprime simplement la version JS du modèle de vue.

 <script type='text/javascript'> var dataToSendToServer = ko.toJS(viewModel); </script> 

Dans certains sanarios, où seule une partie du modèle de vision est en train de changer (ceci est si vous effectuez des mises à jour AJAX), vous pouvez faire des trucs intéressants comme des modèles de commutation afin que la liaison différente puisse être appliquée. Dans ce cas, nous utilisons un #ID_of_Container en tant que conteneur de la donnée / modèle d'origine et en remplaçant le modèle (qui peut contenir des éléments de liaison de données = "") un nouveau modèle ID_of_Template

 <script type='text/javascript'> ko.cleanNode($("#ID_of_Container")); delete (viewModel.Some_Element_To_Be_Updated); viewModel = ko.mapping.updateFromJS(viewModel, New_Data_For_That_Element); // Use ko.toJS(viewModel) because standard template plugin doesn't understand // knockout observables $("#ID_of_Container").html($("#ID_of_Template").tmpl(ko.toJS(viewModel))) ko.applyBindings(viewModel, $("#ID_of_Container")[0]); </script> 

Une approche que j'explore maintenant est de créer une méthode de service Web supplémentaire appelée ReturnEmptyObject () qui ne fait que créer et renvoyer un nouvel objet instancier (dont les propriétés seraient des valeurs par défaut) du côté du serveur. L'objet (dans mon cas C #) est sérialisé sur JSON et enfin arrive sur l'appel JQuery Ajax …. puis est passé dans ko.mapping.updateFromJS () … qui crée les observables nécessaires sur le chargement initial de la page. . Avant d'appeler ko.applyBindings ().

Lorsque ko.applyBindings () s'exécute, il trouve les informations dont il a besoin pour ne pas lancer une erreur, même si elles sont pour la plupart vides.

De cette façon, la page peut initialement être ouverte sans aucun des champs remplis. Pourtant, si j'ajoute de nouvelles propriétés à ma classe du côté du serveur, elles s'affichent automatiquement du côté client.