Handlebars.js: El manillar no funciona en las mesas.

Creado en 15 ago. 2013  ·  37Comentarios  ·  Fuente: handlebars-lang/handlebars.js

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

Tenga en cuenta que los mismos manillares #cada uno tiene éxito cuando están fuera de las mesas. Mi jsfiddle incluye dos salidas bordeadas que demuestran esto.

Comentario más útil

Sé que este problema es bastante antiguo, pero me encontré con esto recientemente debido a que el editor de plantillas de correo electrónico de Sendgrid no sigue estas mejores prácticas. Si alguien más termina con este problema de Google por ese motivo, una solución es colocar el código del manillar en un comentario HTML.

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

que produce la siguiente salida

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

(NOTA: No he verificado esto directamente con Handlebars, solo en el editor de plantillas de Sendgrid)

Todos 37 comentarios

Por lo que vale, si las etiquetas {{each}} se colocan fuera de la tabla, las otras etiquetas funcionan. Por supuesto, esto tiene el efecto indeseable de duplicar la tabla repetidamente, pero quizás ayude a reducir el problema:

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

Esto parece que podría ser un problema con jQuery u otra cosa ... cuando haces console.log(frag); ves que el ayudante {{#each}} se empuja fuera de la tabla incluso antes de intentar compilarlo con manubrios ...

Actualicé jsfiddle para poner la plantilla dentro de una etiqueta <script type="text/x-handlebars-template"></script> y parece que funciona bien ...

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

Sí, acabo de descubrir que yo mismo:
http://jsfiddle.net/cwYhN/10/

Por lo que vale, creo que es el navegador arrojando lo que considera html no válido, en lugar de un defecto de jquery.

Sí, no estaba seguro de si serían cosas de jQuery o la función nativa del navegador que llama jQuery. De cualquier manera, no le gusta el {{ }} entre tbody y tr .

Sería bueno si los manillares se construyeran de alguna manera para operar dentro de esta restricción. Por ejemplo, poder colocar "cada uno" dentro de una etiqueta mientras se tiene el entendimiento implícito de que itera sobre el contenido de la etiqueta. Me imagino que se ve así:

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

Permitir algo como esto evitaría que el navegador elimine lo importante de cada declaración, y podría aprovechar la etiqueta de cierre a la que pertenece (/ tbody)

Como ustedes ya han aludido, el analizador HTML se confunde con el marcado del manillar y aparece esto como la estructura DOM que intenta convertir en una plantilla de manillar:

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

Debería usar algo como el comportamiento de la secuencia de comandos anterior, cadenas de JavaScript o precompilación para solucionar esto.

Cerrar esto como este problema es más un detalle de implementación del navegador que un error en el propio manillar.

Perdí medio día antes de descubrir que {{#each}} no funciona en tablas. Sería realmente útil si esto simplemente se hubiera indicado en la documentación.

Cada uno funciona perfectamente bien en las tablas si se carga correctamente. ¿Cómo estás cargando tus plantillas?

@preichelt Debes cargar los manubrios desde dentro de las etiquetas del script para evitar que el navegador estropee {{#each}} en las tablas. Puede leer más sobre el desbordamiento de pila:

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

Este error desperdició dos horas de mi vida y ahora son las 10:30 p. M. Del sábado, estoy trabajando en mi oficina solo para resolver este error hasta que encontré este problema y [Official Block Doc]
(http://handlebarsjs.com/builtin_helpers.html) no dice nada al respecto.

En caso de que no estuviera claro, esto no es culpa del manillar, sino de usted por no saber cómo funciona HTML: https://html.spec.whatwg.org/multipage/syntax.html#an -introduction-to-error -manipulación-y-casos-extraños-en-el-analizador

Entonces, ¿asume que todos los que intentan usar Handlebarsjs deberían tener una buena comprensión de cómo funciona el analizador HTML? Y si no es así, ¿es culpa del usuario, no de la claridad de la documentación? Esta suposición no tiene sentido. Otro motor de plantillas pesado y complejo, Angularjs, usa sintaxis compatible con Html como sintaxis de plantilla, por ejemplo, si necesito hacer un bucle en la tabla, puedo usar

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

Y Angularjs mantiene el estado interno del bucle mediante el uso de comentarios Html:

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

Angualrjs intenta respetar y seguir la sintaxis de Html tanto como sea posible y evitar la suposición con éxito. Pero la sintaxis de la plantilla de Handlebarsjs no lo hace, por lo que expone el problema del analizador Html a los usuarios.
Si tu desarrollador no puede resolver el problema de tu lado y luego tienes el _ deber_ de decirle a tus usuarios que estén al tanto del problema si realmente te preocupas por tu proyecto y tus usuarios de todo el mundo.
De todos modos, abriré un problema de documento porque _ creo que no soy el primero en encontrar este problema de dolor de cabeza y no seré el último. _

Angular se ejecuta en DOM, por lo que es consciente de DOM. Handlebars funciona solo con cuerdas y no tiene el concepto de DOM.

@profullstack : Como dijo @stevenvachon , Handlebars no funciona con HTML, sino solo con texto. Pero esto puede no ser obvio en los documentos, ya que todos los ejemplos son HTML. Personalmente lo usa también para generar rebajas ...

Si pudiera decirme qué tipo de texto hubiera necesitado en los documentos, estaría encantado de agregarlo. Sin embargo, las instrucciones generales de uso (incluida la parte con la etiqueta <script> ya se encuentran en la página principal de http://handlebarsjs.com/. Por eso no estoy seguro de cuál es su necesidad aquí.

@profullstack Entiendo que está frustrado por haber "perdido el tiempo", pero en mi opinión, lo ha entendido completamente al revés.

Ningún proyecto de código abierto ni contribuyente tiene ningún deber para con usted. Herramientas como los manillares se crean y mantienen de forma gratuita y casi sin agradecimiento, para tratar de hacer la vida más fácil a otros desarrolladores. Si no pudieras utilizar ningún proyecto de código abierto, ¿cuánto tiempo habría tardado tu trabajo?

Les puedo decir, de primera mano, que venir y escribir comentarios con un tono como este tendrá el efecto contrario al deseado . Simple zanahoria vs palo, si quieres que alguien haga algo por ti, pregúntale amablemente o mejor, sube un PR y hazlo tú mismo.

@ErisDS Gracias por tu consejo. Tal vez mi primer comentario fue demasiado fuerte, pero estoy totalmente de acuerdo con tu opinión sobre:

to try to making other developers lives easier

¿Y por qué dejo caer Angularjs para usar Handlebarsjs? _Porque creo que Handlebarsjs hará mi vida más fácil que Angularjs._
Entonces, ¿simplemente agregue algunas palabras de aviso en la documentación para ayudar a sus miles de usuarios de código abierto a evitar el problema potencial que está en contra de su voluntad de "hacer la vida más fácil a otros desarrolladores"? Supongo que no.
Para:

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

Sí, es verdad. Puede iniciar un proyecto de código abierto y luego soltarlo, está totalmente bien. Pero cuando tu proyecto crece, dedicas más tiempo y corazón a tu proyecto, te encanta más tu proyecto y también quieres compartirlo con el mundo. En este momento, comenzará a _preocuparse por sus usuarios_ y _ preocuparse por su documentación_. Handlebarsjs está en esta etapa, este no es un proyecto pequeño, es un proyecto popular y utilizado por programadores de todo el mundo, incluso en Corea del Sur, en China, etc.
Hasta donde yo sé, la mayoría de los programadores de código abierto en Github están orgullosos de su proyecto y su archivo README.md, y desean que cada vez más personas utilicen sus herramientas y códigos.
Así que si:

  • No quiere preocuparse por sus usuarios de código abierto
  • Soy el último que se encontrará con este problema.
    Puede ignorar totalmente mi análisis técnico en el primer comentario y la amable discusión del usuario en este comentario.
    Además, el proyecto de código abierto no es algo así como _caridad_ que le das al mundo, es el _ puente de comunicación_ entre tú y otros programadores.

@nknapp Gracias por tu respuesta.
Tal vez mi primer comentario sea demasiado fuerte y me disculpo por eso y por las personas que lo leyeron.
A primera vista, Handlebars funciona simplemente como _una herramienta de reemplazo de texto_ y es realmente fácil de entender. Entonces, cuando escribo algo como esto:

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

Si es simplemente un reemplazo, esperaría algo como esto:

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

Pero cuando se encuentra con HTML, se comporta de manera diferente, y es debido a la naturaleza del analizador de HTML, tal como @stevenvachon señaló amablemente.
Así que supongo que solo una oración será suficiente debajo de la sección "El asistente de cada bloque":

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)

Realmente agradecería que comparta su opinión. Gracias.

El caso es que esto no tiene nada que ver con el #each -helper. Uno nunca debe escribir una plantilla directamente en HTML. Una declaración como esta debería estar en la página principal, pero la pregunta es: ¿La habría leído allí?

Tal vez podríamos recibir una advertencia como la suya debajo del ejemplo en la página de destino ...

Solo otra nota:

No usaría el método de bloques de script en producción. En su lugar, usaría Webpack u otra herramienta para precompilar las plantillas.

@nknapp Sí, supongo que tu opinión es correcta: nunca deberíamos escribir una plantilla directamente en HTML. Así que supongo que en la página de destino, la primera sección "Comenzando" debería usar un script como ejemplo y en el bloque gris de abajo, podemos cambiar

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

para

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

Supongo tu sugerencia:

**never** write a template directly into HTML

es totalmente correcto, y debe colocarse en la página de destino para que todos lo sigan y pueda evitar muchos problemas. Supongo que es una buena idea, ¿lo crees?

Sin embargo, esa explicación no funciona porque podrían comprenderla como:

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

@stevenvachon Sí, solo poner plantillas dentro del script no es suficiente en su ejemplo, tal vez necesitemos agregar más notas sobre la forma correcta de usar una plantilla, nos gustaría escuchar sus sugerencias sobre esto.

Quizás:

Para la mayoría de las aplicaciones de producción, no querrá utilizar el analizador y las plantillas de cadena. Busque la precompilación.

@stevenvachon Gracias por sus comentarios y supongo que será mejor si ponemos su enlace del analizador HTML junto con sus comentarios:

Para la mayoría de las aplicaciones de producción, no querrá utilizar el analizador y las plantillas de cadena. Busque la precompilación. Hay algunos problemas conocidos si usa una plantilla directamente en HTML, por ejemplo, el asistente de bloque #each no funcionará dentro de las tablas debido a cómo funciona el analizador HTML.

Probablemente debería dividirse en

  1. Directamente debajo del ejemplo de etiqueta <script>

Es importante que coloque la plantilla dentro de una etiqueta <script> . No lo coloque en el HTML directamente o el analizador de HTML podría modificarlo (por ejemplo, si contiene una tabla )

  1. Cambie el punto sobre la precompilación a.

Tenga en cuenta que este enfoque no se recomienda para aplicaciones de producción. También es posible precompilar sus plantillas. [...]

En realidad, personalmente ya no usaría Handlebars en el navegador: hay muchos otros frameworks por ahí (no solo Angular y React, sino también Vue y Ractive). Este video es bastante bueno y muestra el problema ...

Utilizo Handlebars en el servidor y como generador de páginas estáticas, pero para la representación del navegador, creo que hay mejores formas.

@nknapp Empecé a escribir handlebars-html-parser para llevarlo al navegador a través de VDOM, pero encontró resistencia .

@nknapp Gracias por tu respuesta. Tus comentarios incluyen:

  1. La importancia de poner una plantilla dentro de una

@profullstack No soy un mantenedor de este proyecto.

He hecho los cambios.

@nknapp Gracias, creo que mucha gente se beneficiará de tus cambios.

Sé que este problema es bastante antiguo, pero me encontré con esto recientemente debido a que el editor de plantillas de correo electrónico de Sendgrid no sigue estas mejores prácticas. Si alguien más termina con este problema de Google por ese motivo, una solución es colocar el código del manillar en un comentario HTML.

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

que produce la siguiente salida

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

(NOTA: No he verificado esto directamente con Handlebars, solo en el editor de plantillas de Sendgrid)

Gracias por ese consejo @gurpreetatwal . ¡Me ahorraste horas de depuración esta noche con ese dato para SendGrid!

@gurpreetatwal pero ¿por qué?

@Lazarencjusz ¿por qué en lo que respecta a por qué funciona la solución o por qué el editor de plantillas de correo electrónico SendGrid no funciona correctamente?

¡Hola! Cuando use elementos div en lugar de una tabla, funcionará.
También reescriba todos los elementos de la tabla en div.

La solución de @gurpreetatwal me funciona en plantillas de Mailchimp / Mandrills para manillares. ¡Gracias por ahorrarme un montón de problemas!

¿Fue útil esta página
0 / 5 - 0 calificaciones