Handlebars.js: Lenker funktioniert nicht in Tabellen

Erstellt am 15. Aug. 2013  ·  37Kommentare  ·  Quelle: handlebars-lang/handlebars.js

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

Beachten Sie, dass die gleichen Handlebars #each außerhalb von Tabellen erfolgreich sind. Meine jsfiddle enthält zwei umrandete Ausgaben, die dies demonstrieren.

Hilfreichster Kommentar

Ich weiß, dass dieses Problem ziemlich alt ist, aber ich bin kürzlich darauf gestoßen, weil der E-Mail-Vorlagen-Editor von Sendgrid diese Best Practices nicht befolgt. Wenn jemand anderes aus diesem Grund dieses Problem von Google hat, besteht eine Problemumgehung darin, den Lenkercode in einen HTML-Kommentar einzufügen.

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

das erzeugt die folgende Ausgabe

<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>

(HINWEIS: Ich habe dies nicht direkt mit Handlebars überprüft, sondern nur im Vorlageneditor von Sendgrid.)

Alle 37 Kommentare

Wenn die Tags {{each}} außerhalb der Tabelle platziert werden, funktionieren die anderen Tags. Dies hat natürlich den unerwünschten Effekt, wenn die Tabelle wiederholt dupliziert wird, aber vielleicht hilft es, das Problem einzugrenzen:

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

Dies scheint ein Problem mit jQuery oder etwas anderem zu sein... wenn Sie console.log(frag); tun, sehen Sie, dass der {{#each}} Helper aus der Tabelle geschoben wird, noch bevor Sie versuchen, ihn mit dem Lenker zu kompilieren ...

Ich habe die jsfiddle aktualisiert, um die Vorlage in ein <script type="text/x-handlebars-template"></script> Tag einzufügen, und es scheint gut zu funktionieren ...

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

Ja, das habe ich gerade selbst entdeckt:
http://jsfiddle.net/cwYhN/10/

Für das, was es wert ist, denke ich, dass es eher der Browser auswirft, der als ungültiges HTML betrachtet wird, als ein jquery-Fehler.

Ja, ich war mir nicht sicher, ob es sich um jQuery-Dinge oder die native Browserfunktion handelt, die jQuery aufruft. Wie auch immer, es mag das {{ }} zwischen tbody und tr .

Es wäre schön, wenn Lenker in irgendeiner Weise gebaut würden, um innerhalb dieser Einschränkung zu funktionieren. Zum Beispiel in der Lage zu sein, das "each" innerhalb eines Tags zu platzieren und gleichzeitig das implizite Verständnis zu haben, dass es über den Inhalt des Tags iteriert. Ich könnte mir vorstellen, dass es so aussieht:

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

Wenn Sie so etwas zulassen, würde der Browser verhindern, dass die wichtigen Anweisungen entfernt werden, und er könnte auf das schließende Tag zurückgreifen, zu dem es gehört (/tbody).

Wie Sie bereits erwähnt haben, wird der HTML-Parser durch das Handlebars-Markup verwirrt und liefert dies als die DOM-Struktur, die Sie in ein Handlebars-Template konvertieren möchten:

            {{#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>

Sollte etwas wie das obige Skriptverhalten, Javascript-Strings oder eine Vorkompilierung verwenden, um dies zu umgehen.

Dies zu schließen, da dieses Problem eher ein Detail der Browserimplementierung als ein Fehler in der Lenkstange selbst ist.

Habe gerade einen halben Tag verschwendet, bevor ich herausgefunden habe, dass {{#each}} in Tabellen nicht funktioniert. Es wäre wirklich hilfreich, wenn dies einfach in der Dokumentation angegeben wäre.

Jeder funktioniert in Tabellen einwandfrei, wenn er richtig geladen wird. Wie laden Sie Ihre Vorlagen?

@preichelt Sie sollten Handlebars innerhalb von Script-Tags laden, um zu verhindern, dass der Browser {{#each}} in Tabellen durcheinander bringt. Sie können mehr über Stapelüberlauf lesen:

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

Dieser Fehler hat zwei Stunden meines Lebens verschwendet und jetzt ist es Samstag 22:30 Uhr.
(http://handlebarsjs.com/builtin_helpers.html) sagt dazu nichts aus.

Falls es nicht klar war, liegt dies nicht am Lenker, sondern an Ihnen, weil Sie nicht wissen, wie HTML funktioniert: https://html.spec.whatwg.org/multipage/syntax.html#an -introduction-to-error -Behandlung-und-seltsamer-Fälle-im-Parser

Sie gehen also davon aus, dass jeder, der versucht, Handlebarsjs zu verwenden, ein gutes Verständnis dafür haben sollte, wie der HTML-Parser funktioniert? Und wenn nicht, dann ist es _die Schuld des Benutzers_, nicht an der Klarheit der Dokumentation? Diese Annahme ist nicht sinnvoll. Eine andere umfangreiche und komplexe Template-Engine, Angularjs, verwendet HTML-kompatible Syntax als Template-Syntax

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

Und Angularjs behält den internen Status der Schleife mithilfe von Html-Kommentaren bei:

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

Angualrjs versucht, die Syntax von Html so weit wie möglich zu respektieren und zu befolgen und die Annahme erfolgreich zu vermeiden. Die Template-Syntax von Handlebarsjs tut dies jedoch nicht, sodass Benutzern das Html-Parser-Problem offengelegt wird.
Wenn Ihr Entwickler das Problem nicht an Ihrer Seite lösen kann und Sie die _Pflicht_ haben, Ihren Benutzern mitzuteilen, dass sie sich des Problems bewusst sein sollen, wenn Sie sich wirklich um Ihr Projekt und Ihre Benutzer aus der ganzen Welt kümmern.
Wie auch immer, ich werde eine Dokumentenausgabe eröffnen, weil _ ich glaube, ich bin nicht der erste, der auf dieses Kopfschmerzproblem gestoßen ist, und ich werde nicht der letzte sein. _

Angular läuft im DOM, ist also DOM-fähig. Handlebars funktioniert nur mit Saiten und hat kein Konzept des DOM.

@profullstack : Wie @stevenvachon sagte, funktioniert Handlebars nicht mit HTML, sondern nur mit Text. Dies ist jedoch aus den Dokumenten möglicherweise nicht ersichtlich, da alle Beispiele HTML sind. Es persönlich verwendet es auch, um Abschläge zu generieren ...

Wenn Sie mir sagen könnten, welche Art von Text Sie in den Dokumenten benötigt hätten, füge ich ihn gerne hinzu. Die allgemeine Gebrauchsanweisung (einschließlich des Teils mit dem <script> -Tag ist jedoch bereits auf der Hauptseite von http://handlebarsjs.com/ vorhanden. Deshalb bin ich mir nicht sicher, was Sie hier benötigen.

@profullstack Ich

Kein Open-Source-Projekt oder Mitwirkender hat Ihnen gegenüber irgendeine Verpflichtung. Tools wie Lenker werden kostenlos und fast ohne Dank erstellt und gewartet, um zu versuchen, anderen Entwicklern das Leben zu erleichtern. Wenn Sie überhaupt keine Open-Source-Projekte nutzen könnten, wie lange hätte Ihre Arbeit gedauert?

Ich kann Ihnen aus erster Hand sagen, dass das Kommen und Schreiben von Kommentaren in einem solchen Ton das Gegenteil des gewünschten Effekts haben wird . Einfach Karotte vs. Peitsche, wenn Sie möchten, dass jemand etwas für Sie tut, fragen Sie nett oder noch besser, machen Sie es selbst.

@ErisDS Vielen Dank für Ihren Rat. Vielleicht war mein erster Kommentar zu stark, aber ich stimme Ihrer Aussage zu:

to try to making other developers lives easier

Und warum lasse ich Angularjs fallen, um Handlebarsjs zu verwenden? _Weil ich glaube, dass Handlebarsjs mein Leben einfacher machen werden als Angularjs._
Also, fügen Sie der Dokumentation einfach einige Hinweise hinzu, um Ihren Tausenden von Open-Source-Benutzern zu helfen, das potenzielle Problem zu vermeiden, das gegen Ihren Willen ist, "anderen Entwicklern das Leben zu erleichtern"? Ich denke, es ist nein.
Zum:

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

Ja, es ist wahr. Sie können ein Open-Source-Projekt starten und es dann fallen lassen, es ist völlig in Ordnung. Aber wenn Ihr Projekt wächst, investieren Sie mehr Zeit und Herz in Ihr Projekt, Sie lieben Ihr Projekt mehr und möchten es auch mit der Welt teilen. Zu diesem Zeitpunkt beginnen Sie, sich _für Ihre Benutzer zu sorgen_ und _sich um Ihre Dokumentation zu kümmern_. Handlebarsjs befindet sich in diesem Stadium, dies ist kein kleines Projekt, es ist ein beliebtes Projekt und wird von Programmierern auf der ganzen Welt verwendet, sogar in Südkorea, in China und so weiter.
Soweit ich weiß, sind die meisten Open-Source-Programmierer auf Github stolz auf ihr Projekt und ihre README.md-Datei und wünschen sich, dass immer mehr Leute ihre Tools und Codes verwenden.
Also wenn:

  • Sie möchten sich nicht um Ihre Open-Source-Benutzer kümmern
  • Ich bin der Letzte, der auf dieses Problem stößt
    Sie können meine technische Analyse im ersten Kommentar und die nutzerfreundliche Diskussion in diesem Kommentar völlig ignorieren.
    Außerdem ist ein Open-Source-Projekt nicht so etwas wie _Wohltätigkeit_, die du der Welt gibst, es ist die _Kommunikationsbrücke_ zwischen dir und anderen Programmierern.

@nknapp Danke für deine Antwort.
Vielleicht ist mein erster Kommentar zu stark und ich entschuldige mich dafür und bei den Leuten, die meinen Kommentar gelesen haben.
Auf den ersten Blick funktioniert Handlebars einfach wie ein _ein Werkzeug zum Ersetzen von Text_ und es ist wirklich leicht zu verstehen. Also wenn ich sowas schreibe:

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

Wenn es nur ein Ersatz ist, würde ich so etwas erwarten:

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

Aber wenn man auf HTML stößt, verhält es sich anders, und das liegt am natürlichen HTML-Parser, wie @stevenvachon freundlicherweise bemerkt hat.
Ich denke also, dass nur ein Satz unter dem Abschnitt "Die einzelnen Blockhelfer" ausreichen wird:

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)

Ich freue mich sehr, wenn Sie Ihre Meinung teilen. Vielen Dank.

Die Sache ist, dass dies nichts mit dem #each -Helfer zu tun hat. Sie sollten nur niemals eine Vorlage direkt in HTML schreiben. Eine Aussage wie diese sollte auf der Hauptseite stehen, aber die Frage ist: Hättest du sie dort gelesen?

Vielleicht könnten wir eine Warnung wie Ihre unter dem Beispiel auf der Landing-Page finden...

Noch ein Hinweis:

Ich würde die script-blocks-Methode nicht in der Produktion verwenden. Stattdessen würde ich Webpack oder ein anderes Tool verwenden, um die Vorlagen vorzukompilieren.

@nknapp Ja, ich denke, Ihre Meinung ist richtig: Wir sollten niemals eine Vorlage direkt in HTML schreiben. Ich denke also, auf der Landing-Page sollte der erste Abschnitt "Getting Started" ein Skript als Beispiel verwenden und im unteren grauen Block können wir ändern

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

zu

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

Ich vermute dein Vorschlag:

**never** write a template directly into HTML

ist völlig richtig und sollte auf der Landing-Page stehen, damit jeder dies verfolgen kann und viele Probleme vermieden werden können. Ich denke, es ist eine gute Idee, meinst du?

Diese Erklärung funktioniert jedoch nicht, da sie es möglicherweise so verstehen:

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

@stevenvachon Ja, es reicht in Ihrem Beispiel nicht aus, nur Vorlagen in das Skript

Womöglich:

Für die meisten Produktionsanwendungen werden Sie die Parser- und String-Vorlagen nicht verwenden wollen. Schauen Sie in die Vorkompilierung.

@stevenvachon Vielen Dank für Ihre Kommentare und ich denke, es ist besser, wenn wir Ihren HTML-Parser-Link zusammen mit Ihren Kommentaren

Für die meisten Produktionsanwendungen werden Sie die Parser- und String-Vorlagen nicht verwenden wollen. Schauen Sie in die Vorkompilierung. Es gibt einige bekannte Probleme, wenn Sie eine Vorlage direkt in HTML verwenden. Beispielsweise funktioniert der #each-Block-Helper aufgrund der Funktionsweise des HTML-Parsers nicht in Tabellen

Es sollte wahrscheinlich aufgeteilt werden in

  1. Direkt unter dem <script> -Tag-Beispiel

Es ist wichtig, dass Sie die Vorlage in ein <script> -Tag einfügen. Fügen Sie es nicht direkt in den HTML-Code ein oder der HTML-Parser könnte es ändern (z. B. wenn es eine Tabelle enthält )

  1. Ändern Sie den Aufzählungspunkt zur Vorkompilierung in.

Bitte beachten Sie, dass dieser Ansatz für Produktionsanwendungen nicht empfohlen wird. Es ist auch möglich, Ihre Vorlagen vorzukompilieren. […]

Eigentlich würde ich persönlich Handlebars im Browser nicht mehr verwenden: Es gibt noch viele andere Frameworks (nicht nur Angular und React, sondern auch Vue und Ractive). Dieses Video ist ziemlich cool und zeigt das Problem...

Ich verwende Handlebars auf dem Server und als Generator für statische Seiten, aber für das Browser-Rendering gibt es meiner Meinung nach bessere Möglichkeiten.

@nknapp Ich habe angefangen, -html- parser zu schreiben, um ihn über VDOMs in den Browser zu bringen, aber er stieß auf Widerstand .

@nknapp Danke für deine Antwort. Ihre Kommentare umfassen:

  1. Die Bedeutung des Einfügens einer Vorlage in a

@profullstack Ich bin kein Betreuer dieses Projekts.

Ich habe die Änderungen vorgenommen.

@nknapp Vielen Dank, ich glaube, viele Leute werden von Ihren Änderungen profitieren.

Ich weiß, dass dieses Problem ziemlich alt ist, aber ich bin kürzlich darauf gestoßen, weil der E-Mail-Vorlagen-Editor von Sendgrid diese Best Practices nicht befolgt. Wenn jemand anderes aus diesem Grund dieses Problem von Google hat, besteht eine Problemumgehung darin, den Lenkercode in einen HTML-Kommentar einzufügen.

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

das erzeugt die folgende Ausgabe

<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>

(HINWEIS: Ich habe dies nicht direkt mit Handlebars überprüft, sondern nur im Vorlageneditor von Sendgrid.)

Danke für diesen Tipp @gurpreetatwal . Mit diesem Leckerbissen für SendGrid hast du mir heute Abend stundenlanges Debuggen erspart!

@gurpreetatwal aber warum?

@Lazarencjusz warum in Bezug darauf, warum der Fix funktioniert oder warum der SendGrid-E-Mail-Vorlageneditor nicht richtig funktioniert?

Hi! Wenn Sie div-Elemente anstelle einer Tabelle verwenden, wird es funktionieren.
Schreiben Sie auch alle Tabellenelemente in div um.

@gurpreetatwal ‚s Lösung funktioniert für mich auf Mailchimp / Mandrills Templating für Lenker. Danke, dass du mir eine Menge Ärger erspart hast!

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen