Home  >  Q&A  >  body text

Maintain responsive Flex properties when iterating arrays using Handlebars

<p>I have the following code (using Handlebars, working code from JSFiddle): </p> <pre class="brush:php;toolbar:false;"><div class="cards-container"> {{#each this.cards}} <div class="card-container container-col-inner col-12 col-md-6 col-lg-3" > <div class="image-card"> <div class="image-content"> <p class="title">{{title}}</p> </div> </div> </div> {{/each}} </div></pre> <pre class="brush:php;toolbar:false;">{ "3columnLayout": false, "cards": [ { "title": "Card 1" }, { "title": "Card 2" }, { "title": "Card 3" } ] }</pre> <p>Basically, it loops through the array of cards and creates a <code>card-container</code> div for each item. Then use bootstrap to assign a CSS class to each div, for example <code>col-md-6</code> so that: </p> <ul> <li>Mobile: Items appear in a single column</li> <li>Tablets: Items appear in 2 columns</li> <li>Desktop: items displayed in 3 columns</li> </ul> <p>This all works as expected and visually gives the desired UI (regardless of the number of cards): Example below: </p> <p>However, as shown in the JSON, I need a property outside of the individual card level to determine whether the desktop should break from a 4-column layout to a 3-column layout. </p> <p>I didn't want to repeat this property for every card in the card array, so reorganized my code as shown in my code snippet (using Handlebars): https://jsfiddle.net/stcfa5wh/20/< ;/p > <p>However, this now means that although I can access the <code>3columnLayout</code> value: the HTML is dumped onto the page, and I can no longer use <code>col</code> in the way I do ;Done before. </p> <p>For example, on a tablet, I could set each <code>image-card</code> to 50% width, but it ignores the need for rows. </p> <p>Can anyone suggest a way to preserve the structure of the HTML while still implementing top-level attributes (e.g. <code>3columnLayout</code>)? </p>
P粉098417223P粉098417223391 days ago514

reply all(1)I'll reply

  • P粉309989673

    P粉3099896732023-09-03 15:46:09

    I don't understand why you stopped using Bootstrap when you tried to implement the 3columnLayout flag. Using Bootstrap, we will create a 3 column layout using class col-lg-4 on each column. Therefore, the conditional expression we need for each column is: {{#if ../3columnLayout}}col-lg-4{{else}}col-lg-3{{/if}} .

    const template = Handlebars.compile(document.getElementById('Template').innerHTML);
    
    const data = {
      "3columnLayout": true,
      "cards": [{
          "title": "Card 1",
        },
        {
          "title": "Card 2",
        },
        {
    
          "title": "Card 3",
    
        },
        {
          "title": "Card 4",
    
        },
        {
          "title": "Card 5",
        },
        {
    
          "title": "Card 6",
        },
        {
          "title": "Card 7",
        },
        {
          "title": "Card 8",
        }
      ]
    }
    
    const output = template(data);
    
    document.getElementById('Output').innerHTML = output;
    .image-card {
      height: 432px;
      background-color: lightblue;
      border: 1px solid;
      margin-bottom: 16px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.7/handlebars.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"/>
    <script id="Template" type="text/template">
      <div class="container">
        <div class="row">
          {{#each this.cards}}
            <div class="col-md-6 {{#if ../3columnLayout}}col-lg-4{{else}}col-lg-3{{/if}}">
              <div class="image-card">
                <div class="image-content">
                  <p class="title">{{title}}</p>
                </div>
              </div>
            </div>
          {{/each}}
        </div>
      </div>
    </script>
    <div id="Output"></div>

    reply
    0
  • Cancelreply