@@ -32,7 +32,7 @@ Done! Now render it wherever you want:
32
32
33
33
.. code-block :: html+twig
34
34
35
- {{ component('Alert', { message: 'Hello Twig Components!' }) }}
35
+ {{ component('Alert', {message: 'Hello Twig Components!'}) }}
36
36
37
37
<twig:Alert message="Or use the fun HTML syntax!" />
38
38
@@ -193,7 +193,7 @@ them as "props" via the a 2nd argument to ``component()``:
193
193
194
194
.. code-block :: twig
195
195
196
- {{ component('Alert', { message: 'Successfully created!' }) }}
196
+ {{ component('Alert', {message: 'Successfully created!'}) }}
197
197
198
198
{{ component('Alert', {
199
199
type: 'danger',
@@ -235,7 +235,7 @@ available in every component template:
235
235
236
236
.. code-block :: html+twig
237
237
238
- <div {{ attributes.defaults({ class: 'alert alert-'~ type }) }}>
238
+ <div {{ attributes.defaults({class: 'alert alert-' ~ type}) }}>
239
239
{{ message }}
240
240
</div>
241
241
@@ -295,17 +295,22 @@ prefix the attribute with ``:`` or use the normal ``{{ }}`` syntax:
295
295
// pass object, array, or anything you imagine
296
296
<twig:Alert : foo="{col: ['foo', 'oof']}" />
297
297
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):
299
303
300
304
.. code-block :: html+twig
301
305
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' #}
304
307
<twig:Alert message="..." withCloseButton="false" />
305
308
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 #}
308
310
<twig:Alert message="..." withCloseButton="{{ false }}" />
311
+
312
+ {# ✅ use the dynamic syntax #}
313
+ <twig:Alert message="..." :withCloseButton="false" />
309
314
310
315
Don't forget that you can mix and match props with attributes that you
311
316
want to render on the root element:
@@ -319,7 +324,7 @@ This requires Twig 3.7.0 or higher:
319
324
320
325
.. code-block :: html+twig
321
326
322
- <twig:Alert{{ ...myAttributes }} />
327
+ <twig:Alert {{ ...myAttributes }} />
323
328
324
329
We'll use the HTML syntax for the rest of the guide.
325
330
@@ -341,7 +346,7 @@ close tag, it's passed to your component template as the block called
341
346
342
347
.. code-block :: html+twig
343
348
344
- <div {{ attributes.defaults({ class: 'alert alert-'~ type }) }}">
349
+ <div {{ attributes.defaults({class: 'alert alert-' ~ type}) }}">
345
350
{% block content %}{% endblock %}
346
351
</div>
347
352
@@ -450,7 +455,7 @@ passed to ``mount()``.
450
455
.. code-block :: html+twig
451
456
452
457
<twig:Alert
453
- : isSuccess="false"
458
+ isSuccess="{{ false }} "
454
459
message="Danger Will Robinson!"
455
460
/>
456
461
@@ -592,7 +597,7 @@ name is determined by the location of the template:
592
597
.. code-block :: html+twig
593
598
594
599
{# templates/components/Button/Primary.html.twig #}
595
- <button {{ attributes.defaults({ class: 'primary' }) }}>
600
+ <button {{ attributes.defaults({class: 'primary'}) }}>
596
601
{% block content %}{% endblock %}
597
602
</button>
598
603
@@ -641,7 +646,7 @@ To tell the system that ``icon`` and ``type`` are props and not attributes, use
641
646
{# templates/components/Button.html.twig #}
642
647
{% props icon = null, type = 'primary' %}
643
648
644
- <button {{ attributes.defaults({ class: 'btn btn-'~type }) }}>
649
+ <button {{ attributes.defaults({class: 'btn btn-'~type}) }}>
645
650
{% block content %}{% endblock %}
646
651
{% if icon %}
647
652
<span class="fa-solid fa-{{ icon }}"></span>
@@ -674,6 +679,17 @@ In your component template, this becomes a block named ``content``:
674
679
675
680
You can also add more, named blocks:
676
681
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
+
677
693
.. code-block :: html+twig
678
694
679
695
<twig:Alert type="success">
@@ -685,17 +701,6 @@ You can also add more, named blocks:
685
701
</twig:block>
686
702
</twig:Alert>
687
703
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
-
699
704
Passing content into your template can also be done with LiveComponents
700
705
though there are some caveats to know related to variable scope.
701
706
See `Passing Blocks to Live Components `_.
@@ -784,7 +789,7 @@ access to some properties or functions from higher components, that can be done
784
789
{# templates/SuccessAlert.html.twig #}
785
790
{% set name = 'Fabien' %}
786
791
{% set message = 'Hello' %}
787
- {% component Alert with { type: 'success', name: 'Bart' } %}
792
+ {% component Alert with {type: 'success', name: 'Bart'} %}
788
793
Hello {{ name }} {# Hello Bart #}
789
794
790
795
{{ message }} {{ outerScope.name }} {# Hello Fabien #}
@@ -802,7 +807,7 @@ Remember though that the ``outerScope`` reference only starts once you're INSIDE
802
807
{# templates/FancyProfileCard.html.twig #}
803
808
{% component Card %}
804
809
{% 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 #}
806
811
{% block content %}
807
812
{{ message }} {# same value as below, indirectly refers to FancyProfileCard::someProp #}
808
813
{{ outerScope.outerScope.this.someProp }} {# directly refers to FancyProfileCard::someProp #}
@@ -818,7 +823,7 @@ Inheritance & Forwarding "Outer Blocks"
818
823
819
824
The ``outerBlocks `` variable was added in 2.10.
820
825
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
822
827
its own, independent template, which *extends * the component's template. This means that
823
828
any blocks that live in the "outer" template are not available. However, you
824
829
*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
831
836
832
837
{% block body %}
833
838
<twig:Alert>
834
- {# block('call_to_action') #} would not work #}
839
+ {# this would NOT work... #}
840
+ {{ block('call_to_action') }}
835
841
842
+ {# ...but this works! #}
836
843
{{ block(outerBlocks.call_to_action) }}
837
844
</twig:Alert>
838
845
{% endblock %}
@@ -852,7 +859,7 @@ We already have a generic ``Alert`` component, so let's re-use it:
852
859
.. code-block :: html+twig
853
860
854
861
{# templates/components/Alert.html.twig #}
855
- <div {{ attributes.defaults({ class: 'alert alert-'~ type }) }}">
862
+ <div {{ attributes.defaults({class: 'alert alert-'~type}) }}">
856
863
{% block content %}{% endblock %}
857
864
</div>
858
865
@@ -863,7 +870,7 @@ that's passed to it via the ``outerBlocks`` variable and forward it into ``Alert
863
870
864
871
{# templates/components/SuccessAlert.html.twig #}
865
872
<twig:Alert type="success">
866
- {% component Alert with { type: 'success' } %}
873
+ {% component Alert with {type: 'success'} %}
867
874
{{ block(outerBlocks.content) }}
868
875
</twig:Alert>
869
876
@@ -884,7 +891,7 @@ component's template:
884
891
.. code-block :: html+twig
885
892
886
893
{# templates/components/MyComponent.html.twig #}
887
- <div{{ attributes }}>
894
+ <div {{ attributes }}>
888
895
My Component!
889
896
</div>
890
897
@@ -904,7 +911,7 @@ Set an attribute's value to ``true`` to render just the attribute name:
904
911
.. code-block :: html+twig
905
912
906
913
{# templates/components/Input.html.twig #}
907
- <input{{ attributes }}/>
914
+ <input {{ attributes }}/>
908
915
909
916
{# render component #}
910
917
<twig:Input type="text" value="" :autofocus="true" />
@@ -917,7 +924,7 @@ Set an attribute's value to ``false`` to exclude the attribute:
917
924
.. code-block :: html+twig
918
925
919
926
{# templates/components/Input.html.twig #}
920
- <input{{ attributes }}/>
927
+ <input {{ attributes }}/>
921
928
922
929
{# render component #}
923
930
<twig:Input type="text" value="" :autofocus="false" />
@@ -929,7 +936,7 @@ To add a custom `Stimulus controller`_ to your root component element:
929
936
930
937
.. code-block :: html+twig
931
938
932
- <div {{ attributes.defaults(stimulus_controller('my-controller', { someValue: 'foo' })) }}>
939
+ <div {{ attributes.defaults(stimulus_controller('my-controller', {someValue: 'foo'})) }}>
933
940
934
941
.. versionadded :: 2.9
935
942
@@ -958,16 +965,16 @@ the exception of *class*. For ``class``, the defaults are prepended:
958
965
.. code-block :: html+twig
959
966
960
967
{# 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>
962
969
963
970
{# render component #}
964
- {{ component('MyComponent', { style: 'color:red' }) }}
971
+ {{ component('MyComponent', {style: 'color:red'}) }}
965
972
966
973
{# renders as: #}
967
974
<button class="bar" type="button" style="color:red">Save</button>
968
975
969
976
{# render component #}
970
- {{ component('MyComponent', { class: 'foo', type: 'submit' }) }}
977
+ {{ component('MyComponent', {class: 'foo', type: 'submit'}) }}
971
978
972
979
{# renders as: #}
973
980
<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
993
1000
</div>
994
1001
995
1002
{# render component #}
996
- {{ component('MyComponent', { style: 'color:red;' }) }}
1003
+ {{ component('MyComponent', {style: 'color:red;'}) }}
997
1004
998
1005
{# renders as: #}
999
1006
<div style="color:red; display:block;">
@@ -1018,7 +1025,7 @@ You can take full control over the attributes that are rendered by using the
1018
1025
</div>
1019
1026
1020
1027
{# render component #}
1021
- {{ component('MyComponent', { style: 'color:red;' }) }}
1028
+ {{ component('MyComponent', {style: 'color:red;'}) }}
1022
1029
1023
1030
{# renders as: #}
1024
1031
<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
1038
1045
</div>
1039
1046
1040
1047
{# render component #}
1041
- {{ component('MyComponent', { style: 'color:red;' }) }}
1048
+ {{ component('MyComponent', {style: 'color:red;'}) }}
1042
1049
1043
1050
{# renders as: #}
1044
1051
<div style="display:block;" style="color:red;"> {# style is rendered twice! #}
@@ -1053,10 +1060,10 @@ Extract specific attributes and discard the rest:
1053
1060
.. code-block :: html+twig
1054
1061
1055
1062
{# render component #}
1056
- {{ component('MyComponent', { class: 'foo', style: 'color:red' }) }}
1063
+ {{ component('MyComponent', {class: 'foo', style: 'color:red'}) }}
1057
1064
1058
1065
{# templates/components/MyComponent.html.twig #}
1059
- <div{{ attributes.only('class') }}>
1066
+ <div {{ attributes.only('class') }}>
1060
1067
My Component!
1061
1068
</div>
1062
1069
@@ -1073,10 +1080,10 @@ Exclude specific attributes:
1073
1080
.. code-block :: html+twig
1074
1081
1075
1082
{# render component #}
1076
- {{ component('MyComponent', { class: 'foo', style: 'color:red' }) }}
1083
+ {{ component('MyComponent', {class: 'foo', style: 'color:red'}) }}
1077
1084
1078
1085
{# templates/components/MyComponent.html.twig #}
1079
- <div{{ attributes.without('class') }}>
1086
+ <div {{ attributes.without('class') }}>
1080
1087
My Component!
1081
1088
</div>
1082
1089
@@ -1100,14 +1107,14 @@ and footer. Here's an example of this:
1100
1107
.. code-block :: html+twig
1101
1108
1102
1109
{# templates/components/Dialog.html.twig #}
1103
- <div{{ attributes }}>
1104
- <div{{ attributes.nested('title') }}>
1110
+ <div {{ attributes }}>
1111
+ <div {{ attributes.nested('title') }}>
1105
1112
{% block title %}Default Title{% endblock %}
1106
1113
</div>
1107
- <div{{ attributes.nested('body') }}>
1114
+ <div {{ attributes.nested('body') }}>
1108
1115
{% block content %}{% endblock %}
1109
1116
</div>
1110
- <div{{ attributes.nested('footer') }}>
1117
+ <div {{ attributes.nested('footer') }}>
1111
1118
{% block footer %}Default Footer{% endblock %}
1112
1119
</div>
1113
1120
</div>
@@ -1162,7 +1169,7 @@ function where you define ``base`` classes that should always be present and the
1162
1169
{% props color = 'blue', size = 'md' %}
1163
1170
1164
1171
{% set alert = cva({
1165
- base: 'alert ',
1172
+ base: 'alert',
1166
1173
variants: {
1167
1174
color: {
1168
1175
blue: 'bg-blue',
@@ -1222,7 +1229,7 @@ with the ``cva()`` function:
1222
1229
// ...
1223
1230
}) %}
1224
1231
1225
- <div class="{{ alert.apply({color, size}, attributes.render('class')) | tailwind_merge }}">
1232
+ <div class="{{ alert.apply({color, size}, attributes.render('class'))| tailwind_merge }}">
1226
1233
{% block content %}{% endblock %}
1227
1234
</div>
1228
1235
@@ -1238,7 +1245,7 @@ when multiple other variant conditions are met.
1238
1245
{% props color = 'blue', size = 'md' %}
1239
1246
1240
1247
{% set alert = cva({
1241
- base: 'alert ',
1248
+ base: 'alert',
1242
1249
variants: {
1243
1250
color: {
1244
1251
blue: 'bg-blue',
@@ -1291,7 +1298,7 @@ If no variants match, you can define a default set of classes to apply:
1291
1298
{% props color = 'blue', size = 'md' %}
1292
1299
1293
1300
{% set alert = cva({
1294
- base: 'alert ',
1301
+ base: 'alert',
1295
1302
variants: {
1296
1303
color: {
1297
1304
blue: 'bg-blue',
0 commit comments