-
-
Notifications
You must be signed in to change notification settings - Fork 315
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
[TwigComponent] [LiveComponent] Add support for embedded live components #913
Conversation
8333edc
to
b158278
Compare
@kbond FYI: had some weird issues with the tests for PHP 8.0 (but ultimately stupid mistake on my part) which are now fixed. Everything is green so I'd love to hear your feedback! |
5c5ef7a
to
8094445
Compare
Rebased my branch + removed an It used to be that
Since embedded components couldn't be live, it follows that live components would always have a live-id (since all of them were guaranteed non-embedded and follow flow 1). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a quick first glance to try to find problems. This is pretty amazing
.github/workflows/test.yaml
Outdated
dependency-versions: lowest | ||
# needed for php 8.0 to skip symfony/stimulus-bundle | ||
composer-options: "--ignore-platform-reqs" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can all likely be reverted now - the lowest php version and test matrix have all been updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
} | ||
if ($mounted->hasExtraMetadata('hostTemplate') && $mounted->hasExtraMetadata('embeddedTemplateIndex')) { | ||
$mountedAttributes = $mountedAttributes->defaults([ | ||
'data-host-template' => $mounted->getExtraMetadata('hostTemplate'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This exposes the raw Twig template name to the frontend, right? I totally get why, but I don't LOVE it. And I also can't think of a GREAT way around it. We could... encrypt it using the secret? Or... in theory could we, during cache warmup, use the twig.template_iterator
service to create a "map" of "random string => template name"?
Edit: I chatted with kbond - he seems to like the cache warmup idea, if we can pull it off :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed via Slack, I wondered if this was a big deal, but as agreed that it's just to be on the safe side, I'll look into the cache warmup option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added the suggested cache warmer, and obscured the host template attribute through the resulting map.
b2405b7
to
8f82680
Compare
I noticed that live (now embedded) components would always re-render, unlike non-embedded components which would only re-render if a LiveProp changed that also allowed the parent component to update the child component. If none of those LiveProps changed no re-render would happen as of 2.8. This is because of the However, because non-embedded components are rendered via the I added a new commit to take care of this. |
155ffb9
to
69aefec
Compare
I added a change to make embedded components also be part of the component stack, by which it is determined to add a fingerprint. |
1aaedd4
to
7ddd920
Compare
@kbond @weaverryan can you guys have another look at this PR? |
public function createAndRender(string $name, array $props = []): string | ||
/** | ||
* Allow the render process to be short-circuited. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dispatch an event before rendering to give an opportunity to short-circuit the rendering process.
7ddd920
to
d9dd3fc
Compare
This is highly technical, but WOW! I can't believe you got this working. I played with it locally, and it's a ton of fun. Great work Bart! Now, time for some docs about this - we need to be sure to mention the limitation of "relying" on an outside variable from within the embedded template contents. |
…ts doc (sneakyvv) This PR was squashed before being merged into the 2.x branch. Discussion ---------- [TwigComponent][LiveComponent] Add Embedded Live Components doc | Q | A | ------------- | --- | Bug fix? | no | New feature? | no | Tickets | | License | MIT Adds documentation for the feature added by #913 Commits ------- a62c813 [TwigComponent][LiveComponent] Add Embedded Live Components doc
Context
Using embedded components was introduced in #317, but support for Live embedded components was not added. The issue is that on a re-render of a Live component you lose the blocks defined within an embedded component. This PR solves that issue.
Example
To explain the solution, take this example:
Of course, Foo is a Live component.
This obviously also works with the new Twig syntax.
Background
{% component %}
tag is compiled byComponentNode
.It adds an embedded Template to the Template class compiled for
someTemplate.html.twig
. This is a second class inside the same php file, with a suffix in the form of___%d
. That number at the end is normally random, and is called the embedded template index.ComponentNode
would generate Template code which fetches theembeddedContext
from theComponentRenderer
and passed that to theloadTemplate('Foo.html.twig', $index)->display()
(Foo.html.twig
), which does not have the original block content, because that's part of the host Template (someTemplate.html.twig
).Solution
We only need to use the embedded Template instead of the component Template to re-render a component.
To make this happen, we need to:
Remaining
loadTemplate
now in theComponentRender
, which is marked as internal in the Twig package. Can we ignore that within this package (as both are "Symfony")?PreRenderEvent::EMBEDDED
constant and theisEmbedded
function were introduced to block live embedded components. Should this PR remove those as well?Tasks
isEmbedded
?PreRenderEvent::EMBEDDED
?