Closed bob2517 closed 1 year ago
Actually, it should be easier than that to implement. Extract out the {: :} and create an internal mid-way event between beforeComponentOpen and componentOpen. If the render command runs in that event, the result gets stored in the HTML block placeholder prior to render, unless rendering from inside a target selector, as I think we can get additional target selectors in there too. So the top-level render in the HTML block will treat the HTML block as the "event selector". Something like that. No delays allowed though - not even await. Not for first implementation anyway.
This is pretty much done offline, just need to test the component scoping, looping, targets and nested components to make sure they work as expected and should be able to get it onto the branch today if all goes well.
Format will be as above, example:
@component hello-world {
html {
<div>
{:
@if ($okToSayHello) {
render: "Hello world.";
}
body {
render-before-end: "This text is outside the component.";
}
:}
</div>
}
}
At a glance, this looks easy to read and thus that much less effort to understand.
Yes, it's another missing piece of the puzzle I think. A good bonus is the ability to loop an array of strings in there and render the concatenated results - hopefully that will work as expected.
Shadow DOM components work, and loops too, example:
@component hello-world shadow {
html {
<ul>
{:
@for n from 1 to 10 {
render: "<li>{n} Hello world.</li>";
}
:}
</ul>
}
}
All render commands are concatenated into one result before finally rendering on the page, which is something that has been missing in the core up to now.
Very nice!
Yes indeed. Multiple blocks are working too, example:
@component hello-world shadow {
html {
<ul>
{:
@for n from 1 to 10 {
render: "<li>{n} Hello world.</li>";
}
:}
</ul>
<ul>
{:
@for n from 1 to 10 {
render: "<li>{n} Something else.</li>";
}
:}
</ul>
}
}
There's a bug with passing variables into nested components - this doesn't work yet - the attribute variable isn't being recognised inside the nested component:
@component hello-world strictlyPrivate {
&:beforeComponentOpen {
$arr: [ 'Bob', 'Geoff', 'Tracey' ];
}
html {
<ul>
{:
@each $person in $arr {
render: "<li><a-person name='{$person}'></a-person></li>";
}
:}
</ul>
}
}
@component a-person {
html {
Hello {@host:name}.
}
}
I'm going to commit the current state of things to the branch anyway, as the component scoping for events and variables and general nesting seems to be working. Will fix this bug though before release.
Fix for attribute references using {@host:...
for nested components is now on the branch.
Closing pending release.
Possible syntax - this came up in a conversation a while back and it should get an issue:
The render target "selector" would be the html string block itself, and the target selector for everything else would be the component host. The scope would be determined by the component. Some commands wouldn't make sense in there. But if I tie it into the general event flow it could in theory run most if not all the commands that would make sense to run, such as loops, etc. Will ponder this one while I'm doing the pre-rendered component upgrade.
Note to self: Would be easy enough to extract the code within the {: :}, including multiple instances. Just slap a placeholder there at parse time, put the events in the config under a pseudonym, then when rendering the HTML, break off into the sub-events, render at the end of the dummy "target selector" that is actually the half-finished component HTML, and then get back in to the component to finish off the rest of the html block. Probably would be a good idea to disallow the pause command in there, as I suspect that's asking for trouble, and that goes for any delays, like "after stack". It needs to be a smooth run through on the thread or it will get weird. Need to get some more use cases with loops before starting this.