Problem/Motivation
The attribute of a single directory component is shared and not reset between instances, at least on the same page.
This leads to unexpected behaviors, if the developer alter them in the twig file.
Steps to reproduce
Set a basic sdc.
'$schema': 'https://git.drupalcode.org/project/drupal/-/raw/10.1.x/core/modules/sdc/src/metadata.schema.json'
name: test
status: stable
props:
type: object
properties:
my_classes:
type: array
items:
type: string
<div {{ attributes.addClass(my_classes) }}>
{# attributes defined by sdc are problematic #}
{{ dd(attributes.getClass) }}
{# I won't add attributes created manually in the results below, they work as expected #}
{% set my_attribute = create_attribute() %}
{% do my_attribute.addClass(my_classes) %}
{{ dd(my_attribute.getClass) }}
{% block example_block %}
The contents of the example block
{% endblock %}
</div>
Include or embed that sdc into a page, multiple time.
E.g. inside node.hmtl.twig put:
{{ include('olivero:test', { my_classes: ['class-1', 'class-2']}) }}
{{ include('olivero:test', { my_classes: ['class-3', 'class-4']}) }}
{{ include('olivero:test') }}
Expected (?) result of dd(attributes.getClass)
Drupal\Core\Template\AttributeArray {#2103 ▼
#value: array:3 [▼
0 => "contextual-region"
1 => "class-1"
2 => "class-2"
]
#name: "class"
}
Drupal\Core\Template\AttributeArray {#2142 ▼
#value: array:5 [▼
0 => "contextual-region"
3 => "class-3"
4 => "class-4"
]
#name: "class"
}
Drupal\Core\Template\AttributeArray {#2083 ▼
#value: array:1 [▼
0 => "contextual-region"
]
#name: "class"
}
Actual result of dd(attributes.getClass)
Drupal\Core\Template\AttributeArray {#2103 ▼
#value: array:3 [▼
0 => "contextual-region"
1 => "class-1"
2 => "class-2"
]
#name: "class"
Drupal\Core\Template\AttributeArray {#2142 ▼
#value: array:5 [▼
0 => "contextual-region"
1 => "class-1"
2 => "class-2"
3 => "class-3"
4 => "class-4"
]
#name: "class"
}
Drupal\Core\Template\AttributeArray {#1641 ▼
#value: array:5 [▼
0 => "contextual-region"
1 => "class-1"
2 => "class-2"
3 => "class-3"
4 => "class-4"
]
#name: "class"
}
Proposed resolution
The altering a sdc' attribute isn't documented (yet) anywhere, but I took for granted, as I was expecting a full separation of context from them.
I'd suggest they should have a "clean state" between instances.
Comments
Comment #2
giuseppe87 commentedComment #3
giuseppe87 commentedComment #4
larowlanDoes this still happen if you use the only keyword in your include statements https://twig.symfony.com/doc/3.x/tags/include.html
Comment #5
giuseppe87 commentedEither
{% include 'template.html' with {'foo': 'bar'} only %}or{{ include('template.html', {foo: 'bar'}, with_context = false) }}help to mitigate the issue.Namely:
The second and third include won't have the classes of the first.
The second include will have the class of the first, the third won't have them.
I'm saying mitigate because:
Comment #6
giuseppe87 commentedComment #7
larowlanI think what is needed here is a preprocess hook for all SDC components that creates a new Attributes variable.
That's what most theme hooks have to prevent the leakage by default.
Comment #8
giuseppe87 commentedUsing a bit more sdc, I've found another leakage.
I'm also putting into this issue because the cause and solution may be the same.
It's a very weird and corner case I got using the
setcommand.You need two templates: the first,
outer_sdcmust use aset, e.g.:This sdc must be embeded in another sdc/theme twig. The block section must include another sdc:
base_sdccan be a skeleton:The expected output should be:
But actually is
Namely, the
<div data-component-id="my_theme:outer_sdc">has been printed as<div data-component-id="my_theme:base">By the way, this problem doesn't depend on having print
my_contenttwice conditionally.For example if
outer_sdcisThe html render suffers of the same error, so I suppose the problem is something about the
setcommand including a block statement, etc...