Skip to content

Commit 92429e4

Browse files
committed
furthering docs about embedded components
1 parent 2f9568c commit 92429e4

File tree

2 files changed

+98
-14
lines changed

2 files changed

+98
-14
lines changed

src/LiveComponent/README.md

Lines changed: 90 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,15 +1141,79 @@ You can also trigger a specific "action" instead of a normal re-render:
11411141

11421142
## Embedded Components
11431143

1144-
It's totally possible to embed one live component into another. But when
1145-
you do, there are a few things to know:
1144+
Can you embed one live component inside another one? Absolutely! As a rule
1145+
of thumb, **each component exists in its own, isolated universe**. This
1146+
means that embedding one component inside another might be really simple...
1147+
or a bit more complex if your components share "model" data or are
1148+
"connected" in other ways.
11461149

1147-
* When the parent component is re-rendered, the child component is *not*
1148-
automatically re-rendered. Basically, each component operates 100%
1149-
independently of each other.
1150+
Here are a few helpful things to know:
11501151

1151-
For example,
1152-
suppose you have an `EditPostComponent`:
1152+
### Each component re-renders independent of one another
1153+
1154+
If a parent component re-renders, the child component will *not* be updated,
1155+
even though it lives inside the parent. Each component is its own,
1156+
isolated universe.
1157+
1158+
### Actions, methods and model updates in a child do not affect the parent
1159+
1160+
Again, each component is its own, isolated universe! For example, suppose
1161+
your child component has:
1162+
1163+
```html
1164+
<button data-action="live#action" data-action-name="save">
1165+
```
1166+
1167+
When the user clicks that button, it will attempt to call the `save` action
1168+
in the *child* component only, even if the `save` action actually only
1169+
exists in the parent. The same is true for `data-model`, though there is
1170+
some special handling for this case (see next point).
1171+
1172+
### If a child model updates, it will attempt to update the parent model
1173+
1174+
Suppose a child component has a:
1175+
1176+
```html
1177+
<textarea data-model="markdown_value" data-action="live#update">
1178+
```
1179+
1180+
When the user changes this field, this will *only* update the `markdown_value`
1181+
field in the *child* component... because (yup, we're saying it again):
1182+
each component is its own, isolated universe.
1183+
1184+
However, sometimes this isn't what you want! Sometimes, in addition
1185+
to updating the child component's model, you *also* want to update a
1186+
model on the *parent* component.
1187+
1188+
To help with this, whenever a model updates, a `live:update-model`
1189+
is dispatched. All components automatically listen to this event. This
1190+
means that, when the `markdown_value` model is updated in the child
1191+
component, *if* the parent component *also* has a model called `markdown_value`
1192+
it will *also* be updated. This is done as a "deferred" update
1193+
(i.e. [updateDefer()](#deferring-a-re-render-until-later)).
1194+
1195+
If the model name in your child component (e.g. `markdown_value`) is
1196+
*different* than the model name in your parent component (e.g. `post.content`),
1197+
you can make sure both are set by leveraging both the `data-model`
1198+
and `name` attributes:
1199+
1200+
```twig
1201+
<textarea
1202+
data-model="markdown_value"
1203+
name="post[content]"
1204+
data-action="live#update"
1205+
>
1206+
```
1207+
1208+
In this situation, the `markdown_value` model will be updated on the child
1209+
component (because `data-model` takes precedence over `name`). But if
1210+
any parent components have a `markdown_value` model *or* a `post.content`
1211+
model (normalized from `post[content`]`), their model will also be updated.
1212+
1213+
### Full Embedded Component Example
1214+
1215+
Let's look at a full, complex example of an embedded component. Suppose
1216+
you have an `EditPostComponent`:
11531217

11541218
```php
11551219
<?php
@@ -1211,7 +1275,7 @@ In the `EditPostComponent` template, you render the `MarkdownTextareaComponent`:
12111275
<input
12121276
type="text"
12131277
name="post[title]"
1214-
data-action="live#updateDefer"
1278+
data-action="live#update"
12151279
value="{{ this.post.title }}"
12161280
>
12171281
@@ -1228,10 +1292,22 @@ In the `EditPostComponent` template, you render the `MarkdownTextareaComponent`:
12281292
</div>
12291293
```
12301294

1231-
The `MarkdownTextareaComponent`
1295+
```twig
1296+
<div {{ init_live_component(this) }} class="mb-3">
1297+
<textarea
1298+
name="{{ this.name }}"
1299+
data-model="value"
1300+
data-action="live#update"
1301+
>{{ this.value }}</textarea>
1302+
1303+
<div class="markdown-preview">
1304+
{{ this.value|markdown_to_html }}
1305+
</div>
1306+
</div>
1307+
```
12321308

1233-
When you do
1234-
this, there's nothing special to know: both components render independently.
1235-
If you're using [Live Components](https://github.com/symfony/ux-live-component),
1236-
then there *are* some guidelines related to how the re-rendering of parent
1237-
and child components works. Read [Live Embedded Components](https://github.com/symfony/ux-live-component#embedded-components).
1309+
Notice that `MarkdownTextareaComponent` allows a dynamic `name` attribute to
1310+
be passed in. This makes that component re-usable in any form. But it
1311+
also makes sure that when the `textarea` changes, both the `value` model
1312+
in `MarkdownTextareaComponent` *and* the `post.content` model in
1313+
`EditPostcomponent` will be updated.

src/TwigComponent/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,14 @@ class FeaturedProductsComponent
324324
}
325325
```
326326

327+
## Embedded Components
328+
329+
It's totally possible to embed one component into another. When you do
330+
this, there's nothing special to know: both components render independently.
331+
If you're using [Live Components](https://github.com/symfony/ux-live-component),
332+
then there *are* some guidelines related to how the re-rendering of parent
333+
and child components works. Read [Live Embedded Components](https://github.com/symfony/ux-live-component#embedded-components).
334+
327335
## Contributing
328336

329337
Interested in contributing? Visit the main source for this repository:

0 commit comments

Comments
 (0)