-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handlebars doesn't work in tables #604
Comments
For what it's worth, if the {{each}} tags are placed outside of the table, the other tags work. This of course has the undesirable effect if duplicating the table repeatedly, but perhaps it helps narrow down the problem: |
This looks like it might be an issue with jQuery or something else... when you do I updated the jsfiddle to put the template inside a |
Yeah, I just discovered that myself: |
For what it's worth, I think it's the browser throwing out what it considers to be invalid html, rather than a jquery flaw. |
Yeah, I wasn't sure if it would be a jQuery things or the native browser function that jQuery calls. Either way, it doesn't like the |
It would be nice if handlebars built in some sort of way to operate within this constraint. For example, being able to place the "each" within a tag while having the implicit understanding that it iterates over the contents of the tag. I might imagine it looks like:
Allowing for something like this would prevent the browser from stripping out the important each statement, and it could piggyback on the closing tag that it belongs to (/tbody) |
As you guys have already alluded to, the HTML parser is confused by the handlebars markup and comes up with this as the DOM structure that you try to convert to a handlebars template:
Should use something like the script behavior above, javascript strings, or precompilation to work around this. Closing this out as this issue is more of a browser implementation detail than a bug in handlebars itself. |
Just wasted half a day before finding out that {{#each}} doesn't work in tables. It would be really helpful if this had simply been stated in the documentation. |
Each works perfectly fine in tables if loaded properly. How are you loading your templates? |
@preichelt You should be loading handlebars from within script tags to prevent the browser from messing up {{#each}} in tables. You can read more on stack overflow: http://stackoverflow.com/questions/15386276/why-should-we-wrap-our-templates-inside-script-blocks |
This bug wasted two hours of my life and now it is 10:30pm at Saturday, I am working in my office just to solve this bug until I found this issue and [Official Block Doc] |
In case it wasn't clear, this is not the fault of handlebars, but yours for not knowing how HTML works: https://html.spec.whatwg.org/multipage/syntax.html#an-introduction-to-error-handling-and-strange-cases-in-the-parser |
So, you assume everyone who tries to use Handlebarsjs should have a good understanding of how HTML parser works? And if not, then it is the user's fault, not the fault of the clearness of documentation? This assumption does not make sense. Another heavy and complex template engine, Angularjs, use Html compatible syntax as their template syntax, for example, if I need to loop table, I can use
And Angularjs keeps the internal status of loop by using Html comments:
Angualrjs tries to respect and follow the syntax of Html as much as possible and avoid the assumption successfully. But Handlebarsjs's template syntax does not so it exposes the Html parser problem to users. |
Angular runs in the DOM, so it is DOM aware. Handlebars works with strings only and has no concept of the DOM. |
@profullstack: As @stevenvachon said, Handlebars does not work with HTML, but only with text. But this may not be obvious from the docs, since all examples are HTML. It personally use it also to generate markdown... If you could tell me, what kind of text you would have needed in the docs, I would be happy to add it. However, the general usage instructions (including the part with the |
@profullstack I get that you're frustrated about having "wasted time", but in my opinion, you've got this entirely backwards. No open source project nor contributor has any duty to you. Tools like handlebars are created and maintained for free and with almost no thanks, to try to making other developers lives easier. If you were not able to use any open source projects what-so-ever, how long would your work have taken? I can tell you, first hand, that coming along and writing comments with a tone such as this will have the opposite to the desired effect. Simple carrot vs stick, if you want someone to do something for you, ask nicely or even better raise a PR and do it yourself. |
@ErisDS Thank you for your advice. Maybe my first comment was too strong, but I totally agree with your say about:
And why I drop Angularjs to use Handlebarsjs? Because I believe Handlebarsjs will make my life easier than Angularjs.
Yes, it's true. You can start an open source project and then drop it, it's totally OK. But when your project grows, you spend more time and heart on your project, you are loving more about your project and you also want to share it with the world. At this time you will start to care about your users and care about your documentation. Handlebarsjs is at this stage, this is not a small project, it's a popular project and used by programmers all over the world, even in South Korea, in China and so on.
|
@nknapp Thanks for your reply.
If it is just simply replacement, I would expect something like this:
But when came across HTML, it behaves something different, and it is because of the natual of HTML parser just as @stevenvachon kindly noted.
I really appreciate it if you will share your opinion. Thanks. |
The thing is, that this has nothing to do with the Maybe we could a a warning like yours below the example on the landing-page... Just another note: I would not use the script-blocks method in production. Instead I would use Webpack or another tool to precompile the templates. |
@nknapp Yes, I guess your opinion is right: we should never write a template directly into HTML. So I guess on the landing-page, the first "Getting Started" section should use script as example and in the below gray block, we can change
to
I guess your suggestion:
is totally right, and should be put at the landing-page to let everyone follow this and it can avoid many problems. I guess it's a good idea, do you think so? |
That explanation doesn't work, though, because they might comprehend it as: <script type="text/x-handlebars">
{{#each list as |item|}}
<td>{{item}}</td>
{{/each}}
</script> |
@stevenvachon Yes, just putting templates inside the script is not enough in your example, maybe we need to add more notes about the right way to use a template, we would like to hear your suggestions about this. |
Perhaps:
|
@stevenvachon Thanks for your comments and I guess it will be better if we put your HTML parser link together with your comments:
|
It should probably be split into
|
Actually, I personally would not use Handlebars in the browser anymore: There are many other frameworks out there (not only Angular and React, but also Vue and Ractive). This video is pretty cool and shows the problem... I use Handlebars on the server and as static-page generator, but for browser-rendering, I think there are better ways. |
@nknapp I started writing handlebars-html-parser for use in bringing it to the browser through VDOMs, but it met resistance. |
@nknapp Thanks for your reply. Your comments include:
It contains all the important details and it will be fine if we put your comments on the site. |
@profullstack I'm not a maintainer this project. |
- Mention the importance of using script-tags and no other DOM elements as container for templates - Recommendation to precompile template (rather than just saying "you could") see handlebars-lang/handlebars.js#604
I have made the changes. |
@nknapp Thank you, I believe a lot of people will benefit from your changes. |
I know this issue is quite old, but I ran into this recently due to Sendgrid's email template editor not following these best practices. If anyone else ends up on this issue from Google for that reason, a workaround is to place the handlebars code in a HTML comment. <table >
<tbody>
<!-- {{#each items}} -->
<tr>
<td>{{this.key}}</td>
<td>{{this.value}}</td>
</tr>
<!-- {{/each}} -->
</tbody>
</table> that produces the following output <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> (NOTE: I have not verified this with Handlebars directly, just on Sendgrid's template editor) |
Thanks for that tip @gurpreetatwal . You saved me hours of debugging this evening with that tidbit for SendGrid! |
@gurpreetatwal but why? |
@Lazarencjusz why in regards to why the fix works or why is SendGrid email template editor doesn't work correctly? |
Hi! When you use div elements instead of a table, will be work. |
@gurpreetatwal 's Solution works for me on Mailchimp/Mandrills templating for handlebars. Thanks for saving me a ton of trouble! |
Thanks man!! This really helps a lot! Kudos!! |
http://jsfiddle.net/cwYhN/3/
Notice that the same handlebars #each succeeds when outside tables. My jsfiddle includes two bordered outputs demonstrating this.
The text was updated successfully, but these errors were encountered: