include() function must use with_context = false

Created on 1 December 2024, about 2 months ago

When it is not possible to inject them from slots, include() function is the recommended way to "print" a component from a component template:

{{ include('my-theme:my_component', {
  my_prop_1: foo,
  my_prop_2: true,
  my_slot_1: content,
  my_slot_2: "Lorem ipsum",
}, with_context = false) }}

However, to avoid context leaking and unexpected side effects, it is better to always use with_context = false.

Raise a warning if:

  • with_context is missing
  • with_context is true

With this sentence: "`with_context` must be equal to `false` in include() function to avoid context leaking and unexpected side effects "

✨ Feature request
Status

Active

Version

1.0

Component

Code

Created by

πŸ‡«πŸ‡·France pdureau Paris

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @pdureau
  • πŸ‡«πŸ‡·France pdureau Paris
  • πŸ‡«πŸ‡·France pdureau Paris
  • πŸ‡―πŸ‡΄Jordan Rajab Natshah Jordan

    It’s important to minimize questions when working with new team members, which is why having clear warnings during development is so crucial.
    I got the point of this, It will save time while debugging

    Thanks, Pierre

    How to help?
    Raise a warning while loading the component in the page? or a bulk check command?
    `with_context` must be equal to `false` in include() function to avoid context leaking and unexpected side effects

  • πŸ‡ΊπŸ‡ΈUnited States dalemoore

    What about if a developer actually wants to have access to a variable that's available in the parent component? As someone currently working with at least one other person who is also using native web components, we have had need of this ability a few times already. Thanks to the Shadow DOM, it's sometimes not possible to theme or get to content that's been slotted easily, instead, you have to access it from the parent element. Just something to think about here. I doubt most people will be using web components/shadow DOM, but there is a use case here for not absolutely preventing it (or erroring if you don't use this recommendation).

  • πŸ‡«πŸ‡·France pdureau Paris

    What about if a developer actually wants to have access to a variable that's available in the parent component?

    The variables still go the same way (from Drupal template to component template), they just need to be explicitly passed instead of "magically". Is it an issue?

    I doubt most people will be using web components/shadow DOM

    No, but we expect to have more in the future, so we are very interested about this subject. Especially when we will start the 3.x branch of https://www.drupal.org/project/ui_suite_material β†’

  • πŸ‡ΊπŸ‡ΈUnited States dalemoore

    The variables still go the same way (from Drupal template to component template), they just need to be explicitly passed instead of "magically". Is it an issue?

    I can't say yet, I haven't got to the styling of my own web components in Drupal that I forsee possibly being an issue, but it has been a need outside of Drupal for my co-worker who built a custom app with web components.

    The problem you and @just_like_good_vibes have been assisting with has been a blocker there :) I couldn't get the child components to output properly first, so didn't want to start styling yet until I evaluate UI Patterns!

    If I run into issues, I will be sure to share in an issue. πŸ‘

  • πŸ‡―πŸ‡΄Jordan Rajab Natshah Jordan

    Following with Using Single-Directory Components β†’
    in the Using your new single-directory component β†’

    ​

    Use include():

    Use the Twig include() function if there are no slots or arbitrary HTML properties and the data all follows a defined structure.

    Example of how to use the sdc_examples:my-button component in a Twig template:

    {{ include('sdc_examples:my-button', { text: 'Click Me', iconType: 'external' }, with_context = false) }}

    You’ll need to provide the component ID ([module/theme name]:[component]) of the component.

    Read more about include() in the Twig documentation.

    Use {% embed %}:

    Use a Twig {% embed %} tag if you need to populate slots.

    Example of how to pass in a slot (Twig block) in a card component:

    {% embed 'sdc_examples:my-card' with { header: label } %} 
      {% block card_body %}
        {{ content.field_media_image }} 
        {{ content|without('field_media_image') }} 
        {{ include('sdc_examples:my-button', { text: 'Like', iconType: 'like' }, with_context = false) }} 
      {% endblock %} 
    {% endembed %}
    

    Read more about embed in the Twig documentation.

    Use {% include %}:

    Alternatively to the Twig include() function, there is an include keyword, that can also be used if there are no slots or arbitrary HTML properties and the data all follows a defined structure.

    Example of how to use the sdc_examples:my-button component in a Twig template:

    {% include 'sdc_examples:my-button' with { text: 'Click Me', iconType: 'external' } only %}

    You’ll need to provide the component ID ([module/theme name]:[component]) of the component.

    Read more about include tag on Twig documentation.

    ​

  • πŸ‡«πŸ‡·France pdureau Paris

    hi Rajab, this documentation must be updated. See 🌱 Clarify SDC documentation by toning down Twig blocks promotion Active

  • πŸ‡―πŸ‡΄Jordan Rajab Natshah Jordan

    Yes Pierre, I’m on it, I was just about to! . I thought it would be better to check with you first.

    Currently doing my research to set up and finalize our standards with with_context = false.

  • πŸ‡―πŸ‡΄Jordan Rajab Natshah Jordan

    As a dummy idea.
    Thinking about moving with_context: false to the .component.yml file.
    This approach could allow component makers to decide when to restrict it or not, which would be helpful for nesting.
    Having something like utility_classes as a property in all components

    For example:

    • A link component could be used inside a button component,
    • The button component could then be part of a card component,
    • And the card could be used in a view mode or Layout Builder/Experience Builder (LB/XB).
    • then a section with 3 cards
  • πŸ‡«πŸ‡·France pdureau Paris

    Thinking about moving with_context: false to the .component.yml file.
    This approach could allow component makers to decide when to restrict it or not, which would be helpful for nesting.

    I am not comfortable with this:

    • with_context is not something located in the component itself, but where it is called.
    • with_context is a standard Twig feature
    • So, what is happening if the with_context information from .component.yml is conflicting with the one from Twig include() function?

    Having something like utility_classes as a property in all components

    This is the purpose of the automatically injected attributes prop, which can do more:

    • SEO modules can insert tagging attributes through it
    • Accessibility modules can alter/insert some attributes values (aria-*, role, alt...) through it
    • Translation modules can add the lang attribute when needed
    • Hypermedia modules (HTMX, Hotwire/Turbo...) can insert triggers and behaviours attributes through it
    • Drupal Core's |add_class() and |set_attribute() Twig filters rely on it
    • display builders (like Experience Builder) can insert annotation through it
    • ...

    What to do from UI Patterns for example if all has utility_classes? and will they pass all values from the parent component to the deep child components?

    This is the purpose of Drupal Core's |add_class() filter, which is an explicit and standardized way of doing it.

  • πŸ‡―πŸ‡΄Jordan Rajab Natshah Jordan

    Got it :)

    Alright then, moving away from experimenting with the "dummy idea".
    Back to practical, working logic.

    Looking for a twig file/object scanner to report the "`with_context` must be equal to `false` in include() function to avoid context leaking and unexpected side effects" warning log for component.

Production build 0.71.5 2024