rivets icon indicating copy to clipboard operation
rivets copied to clipboard

Template variables are not rendered when empty component tag used

Open stianl opened this issue 7 years ago • 7 comments

Template variables are not rendered when empty component tag used.

When using <counter-component></counter-component> the variables are not interpolated and the result is:

existingTemplateVar and notExistingTemplateVar and.

If I use <counter-component/> (short tag style instead of empty tag) everything works as expected and the variables are interpolated. The result is:

foo and

See fiddle for demo.

stianl avatar Aug 30 '16 12:08 stianl

That is odd. I played with your fiddle and it seems to me like the template existing in the DOM and being accessed by innerHTML has already stripped the curly braces.

If you look here, seems to be working fine : https://jsfiddle.net/Vornagreg/dwr7gwox/

I console.logged the document.querySelector('.template').innerHTML and the curly braces were already stripped out.

Anyhow, I am not super familiar with how the components work. @jccazeaux You use components all the time right? Can you verify this issue?

Duder-onomy avatar Aug 30 '16 17:08 Duder-onomy

This is strange, although first thing I'd say is that it seems dangerous in the first place to use the innerHTML of an element that is already being parsed by rivets to produce the template string for a rivets component. I'll take a look at what the rivets component code is doing here.

benadamstyles avatar Oct 25 '16 17:10 benadamstyles

It's very hard to pin this down, but I think it's some kind of race condition where the component binding parses the template element's innerHTML while the normal view binding is processing its curly-brace-delimited keypaths. This line inserts processed values before their respective nodes in the template, i.e. existingTemplateVar gets processed and placed before { existingTemplateVar } in the document, even if it is a keypath – so rivets puts the keypath existingTemplateVar into the document, replacing { existingTemplateVar }, and then in a second stage processes that keypath. At least, I think this is what's happening. It is after this first stage and before this second stage that I think the component binding is parsing the element's innerHTML.

I am not confident enough in the intricacies of this to propose a fix. I think the moral of the story is – don't use rivets-parsed html as a template for a rivets component. Going to close this as a wontfix but feel free to continue the discussion if you're unsatisfied!

benadamstyles avatar Oct 25 '16 18:10 benadamstyles

Hi @Leeds-eBooks, thanks for taking the time to look into this. It's an interesting theory with the race condition! Although I'd prefer that rivetsjs worked the same way for <counter-component/> and <counter-component></counter-component> (element of least surprise et.c.) I fully understand your view. It's good that we know have it documented anyway.

PS: On another note, the ThymeLeaf template engine (at least 2.1.4) blatantly refuses to output short style tags (it replaces <counter-component /> with <counter-component></counter-component>) so you won't even be able to create templates that uses short style tags (ie. it prevents you from using rivets-parsed html as template). 😄

stianl avatar Oct 26 '16 07:10 stianl

@stianl I would first ask internet if the short style is even appropriate. Oh, and that's already on SO:
http://stackoverflow.com/questions/3558119/are-self-closing-tags-valid-in-html5 http://stackoverflow.com/questions/23353419/how-to-create-a-self-closing-html5-tag-like-br

Standards and backward compability.

Namek avatar Oct 26 '16 07:10 Namek

@Namek interesting – I didn't know that self closing tags were usually invalid, I never use them. This might explain the difference in behaviour between closing the component tag manually vs self-closing. But unless I misunderstood, @stianl's issue only happens when the valid variant – a manually closed tag – is used.

That SO answer gives a clue to what might be happening here. A self-closing tag is rendered as just an opening tag, making subsequent elements become its children. I think rivets ignores children of component tags, which means that they are not parsed twice by rivets, which is the case with a properly closed component tag (because the element used to provide the component's template string is inside the main rivets view element).

benadamstyles avatar Oct 26 '16 08:10 benadamstyles

I didn't know that self closing tags were usually invalid, I never use them

and tag name must consist of two words with hyphen inbetween.

Glad you made some clue of it.

Namek avatar Oct 26 '16 15:10 Namek