@@ -32,7 +32,7 @@ Done! Now render it wherever you want:
3232
3333.. code-block :: html+twig
3434
35- {{ component('Alert', { message: 'Hello Twig Components!' }) }}
35+ {{ component('Alert', {message: 'Hello Twig Components!'}) }}
3636
3737 <twig:Alert message="Or use the fun HTML syntax!" />
3838
@@ -193,7 +193,7 @@ them as "props" via the a 2nd argument to ``component()``:
193193
194194.. code-block :: twig
195195
196- {{ component('Alert', { message: 'Successfully created!' }) }}
196+ {{ component('Alert', {message: 'Successfully created!'}) }}
197197
198198 {{ component('Alert', {
199199 type: 'danger',
@@ -235,7 +235,7 @@ available in every component template:
235235
236236.. code-block :: html+twig
237237
238- <div {{ attributes.defaults({ class: 'alert alert-'~ type }) }}>
238+ <div {{ attributes.defaults({class: 'alert alert-' ~ type}) }}>
239239 {{ message }}
240240 </div>
241241
@@ -295,17 +295,22 @@ prefix the attribute with ``:`` or use the normal ``{{ }}`` syntax:
295295 // pass object, array, or anything you imagine
296296 <twig:Alert : foo="{col: ['foo', 'oof']}" />
297297
298- Boolean props require using the dynamic syntax:
298+ Boolean props are converted using PHP's type juggling rules. The
299+ string ``"false" `` is converted to the boolean ``true ``.
300+
301+ To pass the boolean ``false ``, you can pass a Twig expression
302+ ``{{ false }} `` or use the dynamic syntax (with the ``: `` prefix):
299303
300304.. code-block :: html+twig
301305
302- {# in this example, the 'false' value is passed as a string
303- (so it's converted automatically to the true boolean value) #}
306+ {# ❌ the string 'false' is converted to the boolean 'true' #}
304307 <twig:Alert message="..." withCloseButton="false" />
305308
306- {# in the following examples, the 'false' value is passed as a boolean property #}
307- <twig:Alert message="..." :withCloseButton="false" />
309+ {# ✅ use the 'false' boolean value #}
308310 <twig:Alert message="..." withCloseButton="{{ false }}" />
311+
312+ {# ✅ use the dynamic syntax #}
313+ <twig:Alert message="..." :withCloseButton="false" />
309314
310315Don't forget that you can mix and match props with attributes that you
311316want to render on the root element:
@@ -319,7 +324,7 @@ This requires Twig 3.7.0 or higher:
319324
320325.. code-block :: html+twig
321326
322- <twig:Alert{{ ...myAttributes }} />
327+ <twig:Alert {{ ...myAttributes }} />
323328
324329We'll use the HTML syntax for the rest of the guide.
325330
@@ -341,7 +346,7 @@ close tag, it's passed to your component template as the block called
341346
342347.. code-block :: html+twig
343348
344- <div {{ attributes.defaults({ class: 'alert alert-'~ type }) }}">
349+ <div {{ attributes.defaults({class: 'alert alert-' ~ type}) }}">
345350 {% block content %}{% endblock %}
346351 </div>
347352
@@ -450,7 +455,7 @@ passed to ``mount()``.
450455.. code-block :: html+twig
451456
452457 <twig:Alert
453- : isSuccess="false"
458+ isSuccess="{{ false }} "
454459 message="Danger Will Robinson!"
455460 />
456461
@@ -592,7 +597,7 @@ name is determined by the location of the template:
592597.. code-block :: html+twig
593598
594599 {# templates/components/Button/Primary.html.twig #}
595- <button {{ attributes.defaults({ class: 'primary' }) }}>
600+ <button {{ attributes.defaults({class: 'primary'}) }}>
596601 {% block content %}{% endblock %}
597602 </button>
598603
@@ -641,7 +646,7 @@ To tell the system that ``icon`` and ``type`` are props and not attributes, use
641646 {# templates/components/Button.html.twig #}
642647 {% props icon = null, type = 'primary' %}
643648
644- <button {{ attributes.defaults({ class: 'btn btn-'~type }) }}>
649+ <button {{ attributes.defaults({class: 'btn btn-'~type}) }}>
645650 {% block content %}{% endblock %}
646651 {% if icon %}
647652 <span class="fa-solid fa-{{ icon }}"></span>
@@ -674,6 +679,17 @@ In your component template, this becomes a block named ``content``:
674679
675680You can also add more, named blocks:
676681
682+ .. code-block :: html+twig
683+
684+ <div class="alert alert-{{ type }}">
685+ {% block content %}{% endblock %}
686+ {% block footer %}
687+ <div>Default Footer content</div>
688+ {% endblock %}
689+ </div>
690+
691+ Render these in the normal way.
692+
677693.. code-block :: html+twig
678694
679695 <twig:Alert type="success">
@@ -685,17 +701,6 @@ You can also add more, named blocks:
685701 </twig:block>
686702 </twig:Alert>
687703
688- Render these in the normal way.
689-
690- .. code-block :: html+twig
691-
692- <div class="alert alert-{{ type }}">
693- {% block content %}{% endblock %}
694- {% block footer %}
695- <div>Default Footer content</div>
696- {% endblock %}
697- </div>
698-
699704Passing content into your template can also be done with LiveComponents
700705though there are some caveats to know related to variable scope.
701706See `Passing Blocks to Live Components `_.
@@ -784,7 +789,7 @@ access to some properties or functions from higher components, that can be done
784789 {# templates/SuccessAlert.html.twig #}
785790 {% set name = 'Fabien' %}
786791 {% set message = 'Hello' %}
787- {% component Alert with { type: 'success', name: 'Bart' } %}
792+ {% component Alert with {type: 'success', name: 'Bart'} %}
788793 Hello {{ name }} {# Hello Bart #}
789794
790795 {{ message }} {{ outerScope.name }} {# Hello Fabien #}
@@ -802,7 +807,7 @@ Remember though that the ``outerScope`` reference only starts once you're INSIDE
802807 {# templates/FancyProfileCard.html.twig #}
803808 {% component Card %}
804809 {% block header %}
805- {% component Alert with { message: outerScope.this.someProp } %} {# not yet INSIDE the Alert template #}
810+ {% component Alert with {message: outerScope.this.someProp} %} {# not yet INSIDE the Alert template #}
806811 {% block content %}
807812 {{ message }} {# same value as below, indirectly refers to FancyProfileCard::someProp #}
808813 {{ outerScope.outerScope.this.someProp }} {# directly refers to FancyProfileCard::someProp #}
@@ -818,7 +823,7 @@ Inheritance & Forwarding "Outer Blocks"
818823
819824 The ``outerBlocks `` variable was added in 2.10.
820825
821- The content inside a ``<twig:{Component}> `` tag should be viewed as living in
826+ The content inside a ``<twig: `` component tag should be viewed as living in
822827its own, independent template, which *extends * the component's template. This means that
823828any blocks that live in the "outer" template are not available. However, you
824829*can * access these via a special ``outerBlocks `` variable:
@@ -831,8 +836,10 @@ any blocks that live in the "outer" template are not available. However, you
831836
832837 {% block body %}
833838 <twig:Alert>
834- {# block('call_to_action') #} would not work #}
839+ {# this would NOT work... #}
840+ {{ block('call_to_action') }}
835841
842+ {# ...but this works! #}
836843 {{ block(outerBlocks.call_to_action) }}
837844 </twig:Alert>
838845 {% endblock %}
@@ -852,7 +859,7 @@ We already have a generic ``Alert`` component, so let's re-use it:
852859.. code-block :: html+twig
853860
854861 {# templates/components/Alert.html.twig #}
855- <div {{ attributes.defaults({ class: 'alert alert-'~ type }) }}">
862+ <div {{ attributes.defaults({class: 'alert alert-'~type}) }}">
856863 {% block content %}{% endblock %}
857864 </div>
858865
@@ -863,7 +870,7 @@ that's passed to it via the ``outerBlocks`` variable and forward it into ``Alert
863870
864871 {# templates/components/SuccessAlert.html.twig #}
865872 <twig:Alert type="success">
866- {% component Alert with { type: 'success' } %}
873+ {% component Alert with {type: 'success'} %}
867874 {{ block(outerBlocks.content) }}
868875 </twig:Alert>
869876
@@ -884,7 +891,7 @@ component's template:
884891.. code-block :: html+twig
885892
886893 {# templates/components/MyComponent.html.twig #}
887- <div{{ attributes }}>
894+ <div {{ attributes }}>
888895 My Component!
889896 </div>
890897
@@ -904,7 +911,7 @@ Set an attribute's value to ``true`` to render just the attribute name:
904911.. code-block :: html+twig
905912
906913 {# templates/components/Input.html.twig #}
907- <input{{ attributes }}/>
914+ <input {{ attributes }}/>
908915
909916 {# render component #}
910917 <twig:Input type="text" value="" :autofocus="true" />
@@ -917,7 +924,7 @@ Set an attribute's value to ``false`` to exclude the attribute:
917924.. code-block :: html+twig
918925
919926 {# templates/components/Input.html.twig #}
920- <input{{ attributes }}/>
927+ <input {{ attributes }}/>
921928
922929 {# render component #}
923930 <twig:Input type="text" value="" :autofocus="false" />
@@ -929,7 +936,7 @@ To add a custom `Stimulus controller`_ to your root component element:
929936
930937.. code-block :: html+twig
931938
932- <div {{ attributes.defaults(stimulus_controller('my-controller', { someValue: 'foo' })) }}>
939+ <div {{ attributes.defaults(stimulus_controller('my-controller', {someValue: 'foo'})) }}>
933940
934941.. versionadded :: 2.9
935942
@@ -958,16 +965,16 @@ the exception of *class*. For ``class``, the defaults are prepended:
958965.. code-block :: html+twig
959966
960967 {# templates/components/MyComponent.html.twig #}
961- <button{{ attributes.defaults({ class: 'bar', type: 'button' }) }}>Save</button>
968+ <button {{ attributes.defaults({class: 'bar', type: 'button'}) }}>Save</button>
962969
963970 {# render component #}
964- {{ component('MyComponent', { style: 'color:red' }) }}
971+ {{ component('MyComponent', {style: 'color:red'}) }}
965972
966973 {# renders as: #}
967974 <button class="bar" type="button" style="color:red">Save</button>
968975
969976 {# render component #}
970- {{ component('MyComponent', { class: 'foo', type: 'submit' }) }}
977+ {{ component('MyComponent', {class: 'foo', type: 'submit'}) }}
971978
972979 {# renders as: #}
973980 <button class="bar foo" type="submit">Save</button>
@@ -993,7 +1000,7 @@ You can take full control over the attributes that are rendered by using the
9931000 </div>
9941001
9951002 {# render component #}
996- {{ component('MyComponent', { style: 'color:red;' }) }}
1003+ {{ component('MyComponent', {style: 'color:red;'}) }}
9971004
9981005 {# renders as: #}
9991006 <div style="color:red; display:block;">
@@ -1018,7 +1025,7 @@ You can take full control over the attributes that are rendered by using the
10181025 </div>
10191026
10201027 {# render component #}
1021- {{ component('MyComponent', { style: 'color:red;' }) }}
1028+ {{ component('MyComponent', {style: 'color:red;'}) }}
10221029
10231030 {# renders as: #}
10241031 <div style="color:red;" style="color:red; display:block;"> {# style is rendered twice! #}
@@ -1038,7 +1045,7 @@ You can take full control over the attributes that are rendered by using the
10381045 </div>
10391046
10401047 {# render component #}
1041- {{ component('MyComponent', { style: 'color:red;' }) }}
1048+ {{ component('MyComponent', {style: 'color:red;'}) }}
10421049
10431050 {# renders as: #}
10441051 <div style="display:block;" style="color:red;"> {# style is rendered twice! #}
@@ -1053,10 +1060,10 @@ Extract specific attributes and discard the rest:
10531060.. code-block :: html+twig
10541061
10551062 {# render component #}
1056- {{ component('MyComponent', { class: 'foo', style: 'color:red' }) }}
1063+ {{ component('MyComponent', {class: 'foo', style: 'color:red'}) }}
10571064
10581065 {# templates/components/MyComponent.html.twig #}
1059- <div{{ attributes.only('class') }}>
1066+ <div {{ attributes.only('class') }}>
10601067 My Component!
10611068 </div>
10621069
@@ -1073,10 +1080,10 @@ Exclude specific attributes:
10731080.. code-block :: html+twig
10741081
10751082 {# render component #}
1076- {{ component('MyComponent', { class: 'foo', style: 'color:red' }) }}
1083+ {{ component('MyComponent', {class: 'foo', style: 'color:red'}) }}
10771084
10781085 {# templates/components/MyComponent.html.twig #}
1079- <div{{ attributes.without('class') }}>
1086+ <div {{ attributes.without('class') }}>
10801087 My Component!
10811088 </div>
10821089
@@ -1100,14 +1107,14 @@ and footer. Here's an example of this:
11001107.. code-block :: html+twig
11011108
11021109 {# templates/components/Dialog.html.twig #}
1103- <div{{ attributes }}>
1104- <div{{ attributes.nested('title') }}>
1110+ <div {{ attributes }}>
1111+ <div {{ attributes.nested('title') }}>
11051112 {% block title %}Default Title{% endblock %}
11061113 </div>
1107- <div{{ attributes.nested('body') }}>
1114+ <div {{ attributes.nested('body') }}>
11081115 {% block content %}{% endblock %}
11091116 </div>
1110- <div{{ attributes.nested('footer') }}>
1117+ <div {{ attributes.nested('footer') }}>
11111118 {% block footer %}Default Footer{% endblock %}
11121119 </div>
11131120 </div>
@@ -1162,7 +1169,7 @@ function where you define ``base`` classes that should always be present and the
11621169 {% props color = 'blue', size = 'md' %}
11631170
11641171 {% set alert = cva({
1165- base: 'alert ',
1172+ base: 'alert',
11661173 variants: {
11671174 color: {
11681175 blue: 'bg-blue',
@@ -1222,7 +1229,7 @@ with the ``cva()`` function:
12221229 // ...
12231230 }) %}
12241231
1225- <div class="{{ alert.apply({color, size}, attributes.render('class')) | tailwind_merge }}">
1232+ <div class="{{ alert.apply({color, size}, attributes.render('class'))| tailwind_merge }}">
12261233 {% block content %}{% endblock %}
12271234 </div>
12281235
@@ -1238,7 +1245,7 @@ when multiple other variant conditions are met.
12381245 {% props color = 'blue', size = 'md' %}
12391246
12401247 {% set alert = cva({
1241- base: 'alert ',
1248+ base: 'alert',
12421249 variants: {
12431250 color: {
12441251 blue: 'bg-blue',
@@ -1291,7 +1298,7 @@ If no variants match, you can define a default set of classes to apply:
12911298 {% props color = 'blue', size = 'md' %}
12921299
12931300 {% set alert = cva({
1294- base: 'alert ',
1301+ base: 'alert',
12951302 variants: {
12961303 color: {
12971304 blue: 'bg-blue',
0 commit comments