Handlebars.js: Le guidon ne fonctionne pas dans les tables

Créé le 15 août 2013  ·  37Commentaires  ·  Source: handlebars-lang/handlebars.js

http://jsfiddle.net/cwYhN/3/

Notez que le même guidon #each réussit en dehors des tables. Mon jsfiddle comprend deux sorties bordées démontrant cela.

Commentaire le plus utile

Je sais que ce problème est assez ancien, mais je l'ai rencontré récemment en raison du fait que l'éditeur de modèle de courrier électronique de Sendgrid ne respecte pas ces meilleures pratiques. Si quelqu'un d'autre se retrouve sur ce problème de Google pour cette raison, une solution de contournement consiste à placer le code du guidon dans un commentaire HTML.

<table >
  <tbody>
    <!-- {{#each items}} -->
    <tr>
      <td>{{this.key}}</td>
      <td>{{this.value}}</td>
    </tr>
    <!-- {{/each}} -->
  </tbody>
</table>

qui produit la sortie suivante

<table>
  <tbody>
    <!--  -->
    <tr>
      <td>my key</td>
      <td>my value</td>
    </tr>
    <!--  -->
    <!--  -->
    <tr>
      <td>my key 2</td>
      <td>my value 2</td>
    </tr>
    <!--  -->
  </tbody>
<table>

(REMARQUE : je n'ai pas vérifié cela avec Handlebars directement, juste sur l'éditeur de modèles de Sendgrid)

Tous les 37 commentaires

Pour ce que ça vaut, si les balises {{each}} sont placées en dehors du tableau, les autres balises fonctionnent. Cela a bien sûr l'effet indésirable si la table est dupliquée à plusieurs reprises, mais cela aide peut-être à réduire le problème :

http://jsfiddle.net/cwYhN/6/

Cela ressemble à un problème avec jQuery ou autre chose... lorsque vous faites console.log(frag); vous voyez que l'assistant {{#each}} est poussé en dehors de la table avant même d'essayer de le compiler avec des guidons ...

J'ai mis à jour le jsfiddle pour mettre le modèle dans une balise <script type="text/x-handlebars-template"></script> et cela semble bien fonctionner...

http://jsfiddle.net/doowb/6GdPy/1/

Oui, je viens de découvrir ça moi-même :
http://jsfiddle.net/cwYhN/10/

Pour ce que ça vaut, je pense que c'est le navigateur qui jette ce qu'il considère comme du code html invalide, plutôt qu'une faille jquery.

Ouais, je ne savais pas si ce serait des choses jQuery ou la fonction de navigateur native que jQuery appelle. Dans tous les cas, il n'aime pas les {{ }} entre tbody et tr .

Ce serait bien si les guidons étaient construits d'une manière ou d'une autre pour fonctionner dans cette contrainte. Par exemple, être capable de placer le "chaque" dans une balise tout en ayant la compréhension implicite qu'il itère sur le contenu de la balise. J'imagine que ça ressemble à :

<table>
  <tbody handlebars="{{each}}">
    ... these get iterated ...
  </tbody>
</table>

Permettre quelque chose comme ça empêcherait le navigateur de supprimer l'important de chaque déclaration, et il pourrait se greffer sur la balise de fermeture à laquelle il appartient (/tbody)

Comme vous l'avez déjà mentionné, l'analyseur HTML est confus par le balisage du guidon et propose ceci comme structure DOM que vous essayez de convertir en modèle de guidon :

            {{#each activity}}

            {{/each}}
        <table style="border:1px solid #ccc;">
        <thead>
            <tr><th>Month</th>
            <th>Imps</th>
            <th>Clicks</th>
            <th>Spend</th>
        </tr></thead>
        <tbody><tr>
                <th>{{month}}</th>
                <td>{{impressions}}</td><td>{{clicks}}</td><td>{{spend}}</td>
            </tr></tbody>
    </table>

Devrait utiliser quelque chose comme le comportement de script ci-dessus, des chaînes javascript ou une précompilation pour contourner ce problème.

Clôturer cela car ce problème est plus un détail d'implémentation du navigateur qu'un bogue dans le guidon lui-même.

Je viens de perdre une demi-journée avant de découvrir que {{#each}} ne fonctionne pas dans les tables. Il serait vraiment utile que cela soit simplement indiqué dans la documentation.

Chacun fonctionne parfaitement dans les tableaux s'il est chargé correctement. Comment chargez-vous vos modèles ?

@preichelt Vous devriez charger les guidons à partir des balises de script pour empêcher le navigateur de gâcher {{#each}} dans les tableaux. Vous pouvez en savoir plus sur le débordement de la pile :

http://stackoverflow.com/questions/15386276/why-should-we-wrap-our-templates-inside-script-blocks

Ce bogue a gaspillé deux heures de ma vie et maintenant il est 22h30 samedi, je travaille dans mon bureau juste pour résoudre ce bogue jusqu'à ce que je trouve ce problème et [Official Block Doc]
(http://handlebarsjs.com/builtin_helpers.html) ne dit rien à ce sujet.

Au cas où ce ne serait pas clair, ce n'est pas la faute des guidons, mais la vôtre pour ne pas savoir comment fonctionne HTML : https://html.spec.whatwg.org/multipage/syntax.html#an -introduction-to-error -traitement-et-cas-étranges-dans-le-parseur

Donc, vous supposez que tous ceux qui essaient d'utiliser Handlebarsjs devraient avoir une bonne compréhension du fonctionnement de l'analyseur HTML ? Et si non, alors c'est _la faute de l'utilisateur_, pas la faute de la clarté de la documentation ? Cette hypothèse n'a pas de sens. Un autre moteur de modèle lourd et complexe, Angularjs, utilise la syntaxe compatible Html comme syntaxe de modèle, par exemple, si j'ai besoin de boucler une table, je peux utiliser

<tr ng-repeat="dto in tableData">

Et Angularjs conserve le statut interne de la boucle en utilisant des commentaires Html :

<!-- ngRepeat: column in row -->
<tr ng-repeat="dto in tableData">

Angualrjs essaie de respecter et de suivre la syntaxe de Html autant que possible et d'éviter l'hypothèse avec succès. Mais la syntaxe du modèle de Handlebarsjs ne le fait pas, elle expose donc le problème de l'analyseur HTML aux utilisateurs.
Si votre développeur ne peut pas résoudre le problème à vos côtés, vous avez alors le _devoir_ de dire à vos utilisateurs d'être conscients du problème si vous vous souciez vraiment de votre projet et de vos utilisateurs du monde entier.
Quoi qu'il en soit, je vais ouvrir un problème de document car _ je crois que je ne suis pas le premier à avoir rencontré ce problème de maux de tête et je ne serai pas le dernier. _

Angular s'exécute dans le DOM, il est donc conscient du DOM. Handlebars ne fonctionne qu'avec des chaînes et n'a aucun concept du DOM.

@profullstack : Comme l' a dit

Si vous pouviez me dire, quel genre de texte vous auriez eu besoin dans les docs, je serais heureux de l'ajouter. Cependant, les instructions générales d'utilisation (y compris la partie avec le <script> -tag sont déjà là sur la page principale de http://handlebarsjs.com/. C'est pourquoi je ne suis pas sûr de ce dont vous avez besoin ici.

@profullstack Je comprends que vous soyez frustré d'avoir "perdu du temps", mais à mon avis, vous avez tout à l'envers.

Aucun projet open source ni contributeur n'a de devoir envers vous. Des outils comme les guidons sont créés et maintenus gratuitement et presque sans merci, pour essayer de faciliter la vie des autres développeurs. Si vous n'aviez pu utiliser aucun projet open source, combien de temps votre travail aurait-il pris ?

Je peux vous dire, de première main, que venir et écrire des commentaires avec un ton comme celui-ci aura le contraire de l'effet souhaité . Simple carotte vs bâton, si vous voulez que quelqu'un fasse quelque chose pour vous, demandez gentiment ou encore mieux, soulevez un PR et faites-le vous-même.

@ErisDS Merci pour vos conseils. Peut-être que mon premier commentaire était trop fort, mais je suis tout à fait d'accord avec ce que vous dites sur :

to try to making other developers lives easier

Et pourquoi je laisse tomber Angularjs pour utiliser Handlebarsjs ? _Parce que je pense que Handlebarsjs me rendra la vie plus facile que Angularjs._
Alors, veuillez simplement ajouter quelques mots d'avertissement dans la documentation pour aider vos milliers d'utilisateurs open source à éviter que le problème potentiel soit contre votre volonté de "faciliter la vie des autres développeurs" ? Je suppose que c'est non.
Pour:

No open source project nor contributor has any duty to you.

Oui c'est vrai. Vous pouvez démarrer un projet open source puis le laisser tomber, c'est tout à fait OK. Mais lorsque votre projet grandit, vous consacrez plus de temps et de cœur à votre projet, vous aimez davantage votre projet et vous souhaitez également le partager avec le monde. À ce stade, vous commencerez à vous soucier de vos utilisateurs et de votre documentation. Handlebarsjs en est à ce stade, ce n'est pas un petit projet, c'est un projet populaire et utilisé par des programmeurs du monde entier, même en Corée du Sud, en Chine et ainsi de suite.
Autant que je sache, la plupart des programmeurs open source sur Github sont fiers de leur projet et de leur fichier README.md, et souhaitent que de plus en plus de personnes utilisent leurs outils et codes.
Donc si:

  • Vous ne voulez pas vous soucier de vos utilisateurs open source
  • je suis le dernier a rencontrer ce probleme
    Vous pouvez totalement ignorer mon analyse technique dans le premier commentaire et la discussion conviviale dans ce commentaire.
    De plus, un projet open source n'est pas quelque chose comme la _charité_ que vous offrez au monde, c'est le _pont de communication_ entre vous et les autres programmeurs.

@nknapp Merci pour votre réponse.
Peut-être que mon premier commentaire est trop fort et je m'en excuse ainsi qu'aux personnes qui lisent mon commentaire.
À première vue, Handlebars fonctionne simplement comme _un outil de remplacement de texte_ et c'est vraiment facile à comprendre. Alors quand j'écris quelque chose comme ça :

{{#each myListData}}
                        <tr>{{name}}</tr>
{{/each}}

S'il s'agit simplement d'un remplacement, je m'attendrais à quelque chose comme ceci :

<tr>nameA</tr>
<tr>nameB</tr>

Mais lorsqu'il est tombé sur HTML, il se comporte différemment, et c'est à cause de l'analyseur HTML naturel, comme
Donc, je suppose qu'une seule phrase suffira sous la section "The each block helper":

WARNING: please use script block when you try to use #each block inside table, due to the know issue of [How HTML parse works(thanks for <strong i="18">@stevenvachon</strong>'s reference](https://html.spec.whatwg.org/multipage/syntax.html#an-introduction-to-error-handling-and-strange-cases-in-the-parser)

J'apprécie vraiment si vous partagez votre opinion. Merci.

Le fait est que cela n'a rien à voir avec le #each -helper. Vous ne devriez jamais écrire un modèle directement en HTML. Une déclaration comme celle-ci devrait figurer sur la page principale, mais la question est : l'auriez-vous lu là ?

Peut-être pourrions-nous ajouter un avertissement comme le vôtre sous l'exemple sur la page de destination...

Juste une autre remarque :

Je n'utiliserais pas la méthode des blocs de script en production. Au lieu de cela, j'utiliserais Webpack ou un autre outil pour précompiler les modèles.

@nknapp Oui, je suppose que votre avis est juste : nous ne devrions jamais écrire un modèle directement en HTML. Donc, je suppose que sur la page de destination, la première section "Getting Started" devrait utiliser un script comme exemple et dans le bloc gris ci-dessous, nous pouvons changer

You **can** deliver a template to the browser by including it in a <script> tag.

à

You **should always** deliver a template to the browser by including it in a <script> tag.

Je suppose que votre suggestion:

**never** write a template directly into HTML

est tout à fait juste et devrait être placé sur la page de destination pour permettre à tout le monde de suivre cela et cela peut éviter de nombreux problèmes. Je suppose que c'est une bonne idée, pensez-vous?

Cette explication ne fonctionne pas, cependant, car ils pourraient la comprendre comme:

<script type="text/x-handlebars">
  {{#each list as |item|}}
    <td>{{item}}</td>
  {{/each}}
</script>

@stevenvachon Oui, il ne suffit pas de mettre des modèles dans le script dans votre exemple, nous devons peut-être ajouter plus de notes sur la bonne façon d'utiliser un modèle, nous aimerions entendre vos suggestions à ce sujet.

Peut-être:

Pour la plupart des applications de production, vous ne voudrez pas utiliser les modèles d'analyseur et de chaîne. Regardez dans la précompilation.

@stevenvachon Merci pour vos commentaires et je suppose que ce sera mieux si nous mettons votre lien d'analyseur HTML avec vos commentaires :

Pour la plupart des applications de production, vous ne voudrez pas utiliser les modèles d'analyseur et de chaîne. Regardez dans la précompilation. Il existe des problèmes connus si vous utilisez un modèle directement dans HTML, par exemple, l'assistant de bloc #each ne fonctionnera pas dans les tableaux en raison du fonctionnement de l'analyseur HTML.

Il devrait probablement être divisé en

  1. Directement en dessous de l'exemple de balise <script>

Il est important que vous mettiez le modèle dans une balise <script> . Ne le mettez pas directement dans le code HTML ou l'analyseur HTML pourrait le modifier (par exemple, s'il contient un tableau )

  1. Remplacez la puce de la précompilation par.

Veuillez noter que cette approche n'est pas recommandée pour les applications de production. Il est également possible de précompiler vos modèles. [...]

En fait, personnellement, je n'utiliserais plus Handlebars dans le navigateur : il existe de nombreux autres frameworks (pas seulement Angular et React, mais aussi Vue et Ractive). Cette vidéo est plutôt sympa et montre le problème...

J'utilise Handlebars sur le serveur et comme générateur de pages statiques, mais pour le rendu du navigateur, je pense qu'il existe de meilleurs moyens.

@nknapp J'ai commencé à écrire -html-parser à utiliser pour l'amener au navigateur via des VDOM, mais il a rencontré une résistance .

@nknapp Merci pour votre réponse. Vos commentaires incluent :

  1. L'importance de mettre un modèle à l'intérieur d'un

@profullstack Je ne suis pas un mainteneur de ce projet.

J'ai fait les changements.

@nknapp Merci, je pense que beaucoup de gens bénéficieront de vos changements.

Je sais que ce problème est assez ancien, mais je l'ai rencontré récemment en raison du fait que l'éditeur de modèle de courrier électronique de Sendgrid ne respecte pas ces meilleures pratiques. Si quelqu'un d'autre se retrouve sur ce problème de Google pour cette raison, une solution de contournement consiste à placer le code du guidon dans un commentaire HTML.

<table >
  <tbody>
    <!-- {{#each items}} -->
    <tr>
      <td>{{this.key}}</td>
      <td>{{this.value}}</td>
    </tr>
    <!-- {{/each}} -->
  </tbody>
</table>

qui produit la sortie suivante

<table>
  <tbody>
    <!--  -->
    <tr>
      <td>my key</td>
      <td>my value</td>
    </tr>
    <!--  -->
    <!--  -->
    <tr>
      <td>my key 2</td>
      <td>my value 2</td>
    </tr>
    <!--  -->
  </tbody>
<table>

(REMARQUE : je n'ai pas vérifié cela avec Handlebars directement, juste sur l'éditeur de modèles de Sendgrid)

Merci pour cette astuce @gurpreetatwal . Vous m'avez épargné des heures de débogage ce soir avec cette friandise pour SendGrid !

@gurpreetatwal mais pourquoi ?

@Lazarencjusz, pourquoi le correctif fonctionne-t-il ou pourquoi l'éditeur de modèle d'e-mail SendGrid ne fonctionne-t-il pas correctement ?

Salut! Lorsque vous utilisez des éléments div au lieu d'un tableau, cela fonctionnera.
Réécrivez également tous les éléments de la table en div.

La solution de @gurpreetatwal fonctionne pour moi sur les modèles Mailchimp/Mandrills pour les guidons. Merci de m'avoir épargné une tonne d'ennuis!

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

novwhisky picture novwhisky  ·  4Commentaires

sontek picture sontek  ·  3Commentaires

fcpauldiaz picture fcpauldiaz  ·  4Commentaires

morgondag picture morgondag  ·  5Commentaires

rhariraman picture rhariraman  ·  5Commentaires