underscore.js modèles nesteds

Est-il possible de prendre un élément DOM d’un modèle de soulignement et de l’utiliser comme un autre modèle?

L’idée est que mon application doit afficher un document contenant une boucle contenant des éléments et un résumé. Je dois parfois rendre à nouveau uniquement le résumé ou quelques éléments, je ne peux donc pas simplement restituer tout le document.

Cependant, je souhaiterais que les utilisateurs de l’application conservent leur simplicité pour créer leurs propres modèles pour le document et je pense que tout garder dans un fichier pour un document faciliterait la tâche.

J’essaie d’utiliser quelque chose comme ça:

 

Total items:

Maintenant, je peux facilement faire cela var documentTemplate = _.template($('#document-template').html()); pour en faire un modèle de document, mais je voudrais également transformer la partie récapitulative en modèle et un élément de liste dans un modèle.

Puis-je faire quelque chose comme ça:

 var summaryTemplate = _.template($('#document-template #summary').html()); var itemTemplate = _.template($('#document-template .items li').html()); 

PS En fait, je charge le modèle depuis un fichier externe en utilisant $ .get de jQuery. De cette façon, je vais obtenir le modèle de document dans une grande chaîne. De là, je peux faire juste documentTemplate = _.template(loadedSsortingng); .

Maintenant, si je pouvais simplement extraire l’élément #summary de la chaîne, cela devrait fonctionner. Mais quand j’essaie de convertir la chaîne en élément DOM ( var domElement = $(loadedSsortingng) ) (je pourrais donc le faire: summaryTemplate = _.template($('#summary',domElement).html()); ne fonctionnera pas, car le trait de soulignement ne reconnaîtra plus les balises .

Vous pouvez transmettre le modèle nested en tant que variable dans les affectations de modèle au modèle principal, par exemple:

HTML:

   

JS:

  var renderSub = _.template( $('#sub_template').remove().text() ), renderMain = _.template( $('#main_template').remove().text() ); renderMain({num:5, renderSub:renderSub}); 

Cour de récréation

 /////// TEMPLATES ////// var mainTemplate = "
    \ <% _.each(items, function(item) { %> \ <%= listItem({item:item}) %> \ <% }); %> \
    "; var subTemplate = '
  • <%=item %>
  • '; /////// MODEL (our data) ////// var model = { items : [1,2,3,4,5] } /////// COMPILE ////// // add the subTemplate to the model data, to be passed to the mainTemplate model.listItem = _.template(subTemplate); // Render main template to the DOM document.body.innerHTML = _.template(mainTemplate, model);

Au lieu de le charger en une seule fois en tant que modèle unique et d’essayer ensuite d’en charger une partie ultérieurement, séparez-les en plusieurs modèles.

Ayez votre modèle de document principal et un modèle de résumé. Le chargement initial extrait le modèle de document, puis insère le modèle de résumé et l’insère dans le modèle DOM compilé à partir du premier modèle. Ensuite, vous pouvez recharger le deuxième modèle à tout moment. Voir les étapes suivantes:

1) Chargez le modèle initial, illustré ci-dessous:

  

2) Une fois compilé dans le DOM, chargez le second modèle via le trait de soulignement, illustré ci-dessous:

  

3) Appelez $ (“# document”). Append (summaryTemplate) ou la variable contenant le modèle compilé.

4) Répétez les étapes 2 et 3 chaque fois que vous avez besoin de recharger le récapitulatif, sauf avant de supprimer le $ (“summary”) existant avant de le rappend

Vous pouvez également utiliser cette même stratégie pour les éléments, assurez-vous simplement d’utiliser les sélecteurs / méthodes jQuery corrects pour écraser les div existants dans le bon ordre, car append ne fonctionnera que pour append quelque chose à la fin d’un élément.

Je sais que je suis en retard de 3 ans dans la conversation, mais aucune de ces réponses ne s’applique à une situation que j’avais dans mon dernier projet. Et comme la manière dont je pensais à l’origine a fini par fonctionner, je me suis dit que je devais le poster au cas où quelqu’un voudrait imbriquer des templates underscore.js, comme le dit le titre de cette question.

Mes exigences étaient essentiellement les suivantes:

1) S’il y a des pièces dynamics dans un modèle, elles doivent être capables de se restituer elles-mêmes – sans exiger que le modèle entier soit rendu à nouveau avec les données mises à jour.

2) Les morceaux dynamics ne doivent pas nécessairement être divisés en leurs propres modèles au même niveau que le modèle parent; il devrait plutôt y avoir une sorte de hiérarchie de modèles – un modèle déclarant tous les sous-modèles requirejs pour lui-même.

Le concept des modèles nesteds dans Underscore.js est le même que dans PHP (par exemple). Le code suivant est un exemple de “echoing PHP”:

 '; ?> 

Bien que cette syntaxe nestede puisse devenir super complexe et déroutante, l’idée est simple:

Code d’écho qui fera écho aux valeurs plus tard.

Cela s’applique également aux modèles Underscore.js.


Exemple

Le code ressemblera à ceci:

  

Disons un peu cela. La ligne avec la première NOTE est notre ligne clé ici. Normalement, lorsque Underscore comstack ce modèle, vous vous attendez à ce que la valeur de la value soit imprimée dans les modèles externes et internes. Nous avons fait quelques petites choses pour empêcher cela:

1) Transformez l’instruction de soulignement nestede en une chaîne.

2) Interpoler cette chaîne ( <%= "string here" %> ).

3) Echappez à la fermeture > dans l’instruction de soulignement nestede ( \> ). Cela évite que l'expression régulière d'Underscore ne corresponde à la balise d'ouverture de l'étape 2 ( <%= ). Lorsque cette chaîne est répercutée, le caractère d'échappement sera supprimé, laissant %> , prêt à être interprété par Underscore lors du passage suivant.

Faire la même chose dans la deuxième NOTE de notre exemple empêche le navigateur de mettre fin à la première balise de script . Les balises de script nestedes ne sont techniquement pas autorisées. Le navigateur recherche donc la première séquence de caractères: , puis termine l'exécution du script. Cela empêche le navigateur de reconnaître cette séquence.

Pour un exemple plus détaillé, voir ce JSFiddle .


Avertissements

Je n'approuve pas cela comme la meilleure façon de faire ce genre de chose. Après tout, c'est très pirate. Bien que la réponse de @John z casse ma première exigence, ce qui n'était pas une option pour moi, l'autre option consistant à scinder des pièces dynamics dans un modèle dans leurs propres modèles peut être plus facile à gérer. C'est juste moins organisé.

L'emplacement de toutes ces balises de script nestedes dans votre DOM peut être difficile à suivre (les balises de script nestedes étant injectées dynamicment dans le DOM lorsque vous insérez le modèle externe). Le risque de duplication est élevé et peut être gênant à maintenir.

La difficulté d'imbrication des modèles augmente considérablement pour chaque niveau d'imbrication (pour imbriquer un modèle dans un modèle nested, vous devez tout échapper à nouveau, etc.). Le violon comprend un exemple de cela.