Isolate href from previous calls inside jinja template

Question:

Excuse me if this is something "stupid" or if I’m doing something wrong, but it’s the first time I ever post here and I’m actually trying to learn this thing and be clear in my questoin.

First time I’m working with jinja/templates and I was trying to create a self-populating status page. Something like this:

home.html

{% extends "base.html" %}
{% block title %}Home{% endblock %}

{% block body %}

  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>

{% for envlist in ('dev','qa','prod') %}
<div class="container">
    <h2>Accordion Example - {{ envlist }}</h2>
    <p><strong>Note:</strong> The <strong>data-parent</strong> attribute makes sure that all collapsible elements under the specified parent will be closed when one of the collapsible item is shown.</p>
    {% for monitored in ('facebook','google') %}
    <div class="panel-group" id="accordion{{ envlist }}">
      <div class="panel panel-default">
        <div class="panel-heading">
          <h4 class="panel-title">
            <a data-toggle="collapse" data-parent="#accordion{{ envlist }}" href="#collapse-{{ monitored }}">Collapsible Group {{ monitored }}</a>
          </h4>
        </div>
        <div id="collapse-{{ monitored }}" class="panel-collapse collapse in">
          <div class="panel-body">{{envlist}} - {{monitored}}</div>
        </div>{%endfor%}
      </div>
    </div>
  </div>
{%endfor%}
{% endblock %}

The whole point is to create a "status page" using the collapsible/accordion feature.

What I tried to do: Create 1 accordion for each monitorings (google and facebook as examples) isolating the resources (panel-group = accordion and data-toggle=collpase).

What I think it’s happening: If I get it right, when the second iteration happens, the second accordion gets created (dev), but my attempt to isolate the "collapsible" (href="#collapse-{{ monitored }}") fails miserably as the same href name/id in set both accordions (data-parent – either collapse-google or collapse-facebook). Therefore when I try to collapse the Second Collapsible Group (accordion = dev), it actually collapses the first (accordion = qa) because the href has the same name/id as that first accordion (qa).

My base.html is as simple as possible:

base.html

<!DOCTYPE html>
<html>
  <head>
    <title>{% block title %}BASE{% endblock %}</title>
  </head>
  <body>
    {% block body %} {% endblock %}
    </div>
  </body>
</html>

I tried swapping the forloops and even a desperate attempt to create dedicated "Collapsible Group" by introducing another for around the below:

          <h4 class="panel-title">
            <a data-toggle="collapse" data-parent="#accordion{{ envlist }}" href="#collapse-{{ monitored }}">Collapsible Group {{ monitored }}</a>
          </h4>

No soup for me.

Is there a way of isolating those hrefs some how or something similar? Any help would be of much appreciation. I’m also taking suggestions for this project 🙂

Thanks in advance.

Answers:

You have already found the reason for the lack of demarcation between the accordions. The CSS selector in the href attribute points to a non-unique id for the collapsible. Thus, the first found element with the matching id is used, regardless of which accordion it belongs to. So the goal is to form a unique id for each collapsible.
In the example below, the indices of the two loops are used for this.

{% for envlist in ('dev','qa','prod') %}
{% set loop_idx0 = loop.index0 %}
<div class="container">
    <h2>Accordion Example - {{ envlist }}</h2>
    <p>
        <strong>Note:</strong> The <strong>data-parent</strong> attribute makes sure 
        that all collapsible elements under the specified parent will be closed when 
        one of the collapsible item is shown.
    </p>
    <div class="panel-group" id="accordion-{{ envlist }}">
        {% for monitored in ('facebook','google') %}
        <div class="panel panel-default">
            <div class="panel-heading">
                <h4 class="panel-title">
                    <a 
                        data-toggle="collapse" 
                        data-parent="#accordion-{{ envlist }}" 
                        href="#collapse-{{ loop_idx0 }}-{{ loop.index0 }}"
                    >Collapsible Group {{ monitored }}</a>
                </h4>
            </div>
            <div 
                id="collapse-{{ loop_idx0 }}-{{ loop.index0 }}" 
                class="panel-collapse collapse {{ ('', 'in')[loop.first] }}"
            >
                <div class="panel-body">{{envlist}} - {{monitored}}</div>
            </div>
        </div>
        {%endfor%}
    </div>
</div>
{%endfor%}
Answered By: Detlef
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.