Skip to content

Commit 15fc0f8

Browse files
committed
Adding explanations to the invoice live demo
1 parent 914ec7d commit 15fc0f8

File tree

4 files changed

+62
-11
lines changed

4 files changed

+62
-11
lines changed

ux.symfony.com/assets/styles/_type.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,3 +224,8 @@ h4.ubuntu {
224224
color: $n-300;
225225
font-weight: lighter;
226226
}
227+
228+
blockquote {
229+
border-left: 5px solid $n-200;
230+
padding-left: 1rem;
231+
}

ux.symfony.com/templates/components/InvoiceCreatorLineItem.html.twig

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
>
99
<option value="" {{ not product ? 'selected' }}>Choose a Product</option>
1010
{% for productOption in products %}
11-
<option value="{{ productOption.id }}" {% if productOption == product %}selected{% endif %}>
11+
<option
12+
value="{{ productOption.id }}"
13+
{% if productOption == product %}selected{% endif %}
14+
>
1215
{{ productOption.name }} ({{ productOption.priceInCents|format_currency('USD') }})
1316
</option>
1417
{% endfor %}

ux.symfony.com/templates/live_component_demo/invoice.html.twig

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,55 @@
11
{% extends 'liveDemoBase.html.twig' %}
22

33
{% 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>
1053
{% endblock %}
1154

1255
{% block demo_content %}

ux.symfony.com/templates/live_component_demo/product_form.html.twig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Live component with a form, `ValidatableComponentTrait` and a
1010
`saveProduct()` LiveAction for instant validation & an AJAX submit.
1111

1212
The real magic comes from `#[LiveListener('category:created')`. This
13-
is emitted by the [NewCategoryForm](#NewCategoryForm.php) component (which opens
13+
is emitted by the `NewCategoryForm` component (which opens
1414
in a modal) when a new category is created.
1515

1616
Note: the `category:created` event emits `category` as an *integer*.
@@ -20,7 +20,7 @@ Symfony uses that id to query for the `Category` object.
2020
</twig:CodeWithExplanationRow>
2121

2222
<twig:CodeWithExplanationRow filename="templates/components/NewProductForm.html.twig" reversed>
23-
Near the bottom, this renders the [BootstrapModal](#BootstrapModal.php) component with another
23+
Near the bottom, this renders the `BootstrapModal` component with another
2424
component - `NewCategoryForm` - inside of it. Opening the modal is done entirely
2525
with normal Bootstrap logic: an `a` tag with `data-bs-toggle="modal"`
2626
and `data-bs-target="#new-category-modal"`.
@@ -31,9 +31,9 @@ This component opens up in the modal! It has a `#[LiveAction]` that saves
3131
the new `Category` to the database and then does two important things:
3232

3333
1. Emits the `category:created` event with the new `Category`'s id (see
34-
[NewProductForm.php](#NewProductForm.php)).
34+
`NewProductForm.php`).
3535
1. Dispatches a browser event called `modal:closed` to close the modal
36-
(see [bootstrap-modal-controller.js](#bootstrap-modal-controller.js)).
36+
(see `bootstrap-modal-controller.js`).
3737
</twig:CodeWithExplanationRow>
3838

3939

0 commit comments

Comments
 (0)