@@ -1141,15 +1141,79 @@ You can also trigger a specific "action" instead of a normal re-render:
1141
1141
1142
1142
## Embedded Components
1143
1143
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.
1146
1149
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:
1150
1151
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 ` :
1153
1217
1154
1218
``` php
1155
1219
<?php
@@ -1211,7 +1275,7 @@ In the `EditPostComponent` template, you render the `MarkdownTextareaComponent`:
1211
1275
<input
1212
1276
type="text"
1213
1277
name="post[title]"
1214
- data-action="live#updateDefer "
1278
+ data-action="live#update "
1215
1279
value="{{ this.post.title }}"
1216
1280
>
1217
1281
@@ -1228,10 +1292,22 @@ In the `EditPostComponent` template, you render the `MarkdownTextareaComponent`:
1228
1292
</div>
1229
1293
```
1230
1294
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
+ ```
1232
1308
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 .
0 commit comments