How to add a class to item of a list in Drupal 10

I have created an item list inside a foreach loop like

$items[] = [
  '#markup' => 'some html text'
]

then pass it to

themed_list = [
 '#theme' => 'item_list',
 '#items' => $items,  
 '#attributes' => ['class' => ['my-list-class']],
];

this works fine with the Drupal’s standard item_list.html.twig

{% if context.list_style %}
    {%- set wrapper_attributes = wrapper_attributes.addClass('item-list--' ~ context.list_style) %}
    {%- set attributes = attributes.addClass('item-list__' ~ context.list_style) %}
{% endif %}
{% if items or empty -%}
    <div{{wrapper_attributes.addClass('item-list')}}>
        {%- if title is not empty -%}
            <h3>{{ title }}</h3>
        {%- endif -%}
        {%- if items -%}
            <{{list_type}}{{attributes.addClass('list-group')}}>
                {%- for item in items -%}
                    <li{{item.attributes.addClass('list-group-item')}}>{{ item.value }}</li>
                {%- endfor -%}
            </{{list_type}}>
        {%- else -%}
            {{- empty -}}
        {%- endif -%}
    </div>
{%- endif %}

and produces the expected code

<ul class="my-list-class list-group">
  <li class="list-group-item">my html text</li>
...
</ul>

Now I want to add a custom class to the <li> elements so I could display

<li class="list-group-item my-li-class">my html text</li>

I tried

$items[] = [
  '#markup' => 'some html text',
  '#attributes' =>['class' => ['my-li-class]]
]

but this doesn’t have any effect although if I add prefix and suffix

$items[] = [
  '#markup' => 'some html text',
  '#attributes' =>['class' => ['my-li-class]],
  '#prefix' => '<div class="div-class">',
  '#suffix' => '</div>'
],

#prefix and #suffix are correctly displayed.

<li class="list-group-item">
  <div class="div-class">my html text</div>
</li>

What I don’t understand is that both Drupal documentation and twig file comments say

items: A list of items. Each item contains:
   attributes: HTML attributes to be applied to each list item.
   value: The content of the list element.

I tried ‘#value’ and ‘#attributes’ as well as ‘value’ and ‘attributes’ without success. I’m stuck on how can I define the renderable array. Any help welcome.

To achieve your desired outcome, you’ll need to modify the item_list.html.twig template to incorporate the #attributes property into the <li> element’s HTML attributes. Here’s the updated code:

{%- if items -%} <{{list_type}}{{attributes.addClass('list-group')}}> {%- for item in items -%} <li{{item.attributes.addClass('list-group-item my-li-class')}}>{{ item.value }}</li> {%- endfor -%} </{{list_type}}> {%- else -%} {{- empty -}} {%- endif -%}

Explanation:

  1. Locate the item_list.html.twig file: This is typically found within your theme’s templates directory.
  2. Identify the <li> element rendering loop: Look for the {%- for item in items -%} block.
  3. Modify the li attributes: Within the <li> element, add item.attributes to the addClass method. This will combine the existing list-group-item class with your desired my-li-class .

Additional Notes:

  • If you have multiple custom classes to apply, you can concatenate them using addClass(['class1', 'class2']) .
  • Ensure that your theme’s CSS file includes the necessary styles for the my-li-class to be applied correctly.

Example:

$items[] = [ '#markup' => 'Some HTML text', '#attributes' => ['class' => ['my-li-class', 'another-class']] ];

This will now render as:

<li class="list-group-item my-li-class another-class">Some HTML text</li>

By making this modification to the item_list.html.twig template, you’ll effectively add the custom class to the <li> elements within your themed item list, achieving the desired styling.