Bootstrap - La grille dynamique

Créer une grille bootstrap sans connaître le nombre d'éléments à inclure.

Posté le Aug. 20, 2020

Intro

Voici un problème qui mérite un petit article. Le système de grille (bootstrap grid) de bootstrap est formidable seulement il n'est pas très dynamique quant au nombre d'éléments à y inclure. Voici donc comment établir une grille dans un template Django avec un nombre inconnu d'élément.

Solution

Imaginons que nous souhaitons établir une grille à 3 colonnes, voici la version statique (6 éléments, 2 lignes, 3 colonnes) :

<div class="container">
    <div class="row">
        <div class="col-md-4">
            élément 1
        </div>
        <div class="col-md-4">
            élément 2
        </div>
        <div class="col-md-4">
            élément 3
        </div>
    </div>  
    <div class="row">
        <div class="col-md-4">
            élément 4
        </div>
        <div class="col-md-4">
            élément 5
        </div>
        <div class="col-md-4">
            élément 6
        </div>
    </div>  
</div>

Jusqu'à la, tout va bien, sauf que c'est pas dynamique.

Prenons par exemple des postes de blog Wagtail, la boucle initiale est la suivante:

{% for post in self.get_children.specific %}
{% endfor %}

Ici, nous ne connaissons pas le nombre de poste. Le premier élément à déployer est le compteur de boucle:

{{ forloop.counter }}

Inséré dans une boucle for, il compte tout simplement les tours. A noter que celui ci-dessus démarre à 1, pour les puristes qui souhaiteraient commencer à 0, il est possible d'utiliser {{ forloop.counter0 }}

Jusqu'ici tout va bien, maintenant il s'agit de tester le modulo du compteur de boucle, s'il est égal à 0 il faut créer une nouvelle ligne dans la grille. En d'autres termes, si je veux une grille à 3 colonnes, je vais tester si le compteur de boucle est divisible par 3.

<div class="container">
    <div class="row">
    {% for post in self.get_children.specific %}
    {%  if forloop.counter|divisibleby:3 %} 
        <div class="col-md-4">
            {{ post.title }}
        </div>
    </div>
    {% if not forloop.last %} 
    <div class="row">
    {% endif %}
    {% else %} 
        <div class="col-md-4">
            {{ post.title }}
        </div>
    {% endif %}
    {% endfor %}
    </div>
</div>