|
1 | 1 | {% extends 'liveDemoBase.html.twig' %}
|
2 | 2 |
|
3 | 3 | {% block code_block_full %}
|
4 |
| - <twig:TabbedCodeBlocks :files="[ |
5 |
| - 'src/Twig/InvoiceCreator.php', |
6 |
| - 'templates/components/InvoiceCreator.html.twig', |
7 |
| - 'src/Twig/InvoiceCreatorLineItem.php', |
8 |
| - 'templates/components/InvoiceCreatorLineItem.html.twig', |
9 |
| - ]" /> |
| 4 | + <twig:CodeWithExplanationRow filename="src/Twig/InvoiceCreator.php"> |
| 5 | +This main component keeps track of the `Invoice` (which may be new) and |
| 6 | +a list of the "invoice items" - stored on a `LiveProp` called `$lineItems`. |
| 7 | + |
| 8 | +Because `LiveProp` values need to be (mostly) simple, the `$lineItems` are |
| 9 | +stored as a raw array of data, which we add to or remove from when line |
| 10 | +items are added/removed. |
| 11 | + |
| 12 | +This components listens to several events that the child |
| 13 | +`InvoiceCreatorLineItem` components emits. For example, the child emits |
| 14 | +`removeLineItem` when the user clicks the "x" button on a line item. |
| 15 | +This triggers the `removeLineItem()` method on this component, which |
| 16 | +removes the line item from the `$lineItems` array. |
| 17 | + </twig:CodeWithExplanationRow> |
| 18 | + |
| 19 | + <twig:CodeWithExplanationRow filename="templates/components/InvoiceCreator.html.twig" reversed> |
| 20 | +The template is fairly simple: rendering form fields with `data-model` to |
| 21 | +bind to writable `LiveProp`'s along with their validation errors. |
| 22 | + |
| 23 | +Most importantly, this loops over `$lineItems` and renders the |
| 24 | +`InvoiceCreatorLineItem` child component for each one passing the |
| 25 | +data: `productId`, `quantity`, and `isEditing`. It also passes a `key`, |
| 26 | +which is needed so LiveComponents can track which row is which. |
| 27 | + </twig:CodeWithExplanationRow> |
| 28 | + |
| 29 | + <twig:CodeWithExplanationRow filename="src/Twig/InvoiceCreatorLineItem.php"> |
| 30 | +The child component for each "line item". This handles validating, saving, |
| 31 | +and changing the "edit" state of the line item. |
| 32 | + |
| 33 | +But all of the line item data ultimately needs to be stored on the parent |
| 34 | +component so that we can wait to save everything to the database. This |
| 35 | +component communicates the new data (or "edit" state change) to the parent |
| 36 | +by emitting events - e.g. `line_item:save`. |
| 37 | + |
| 38 | +> Note: it would be simpler to manage the `isEditing` state directly on this |
| 39 | +> component, instead of passing it to the parent. It was done this way so that |
| 40 | +> the parent component can know how many of its children are currently in |
| 41 | +> "edit" mode. |
| 42 | + </twig:CodeWithExplanationRow> |
| 43 | + |
| 44 | + <twig:CodeWithExplanationRow filename="templates/components/InvoiceCreatorLineItem.html.twig" reversed> |
| 45 | +Nothing too fancy here: some `data-model` elements and `data-action="live#action"` |
| 46 | +buttons. |
| 47 | + |
| 48 | +The most interesting part is the "X" button to remove a line item: this uses |
| 49 | +`data-action="live#emitUp"` to emit the `removeLineItem` event to the parent component. |
| 50 | +In this case, instead of triggering a `LiveAction` that *then* emits the event, |
| 51 | +we emit the event directly. |
| 52 | + </twig:CodeWithExplanationRow> |
10 | 53 | {% endblock %}
|
11 | 54 |
|
12 | 55 | {% block demo_content %}
|
|
0 commit comments