Search code examples
javascripthtmlhandlebars.jshtml-templates

How to dynamically add class in Handlebars template


I am trying to either dynamically create HTML elements in my Handlebars template, specifically:

<span class="fa fa-star checked"></span>

Or I want to be able to select existing elements and add the 'checked' class to them. It's for a star rating display, if a book has a rating of 5, then I want 5 out of 5 spans to have the checked class and styled appropriately.

So far I've tried using jQuery to target the span elements and add a class ie. $('#star-1').addClass('checked'); But I get a null value when searching for that element.

I've also tried to append child elements to a parent div with a for loop, but I get a similar problem with not being able to find and select the parent container. The closest I've got is shown below with returning a single span element in a for loop or returning 5 span elements without the class. Any help would be appreciated.

In my template.html file:

<div class="rating-container">
    {{#renderStars rating}}
    <span class="fa fa-star" id="star-1"></span>
    <span class="fa fa-star" id="star-2"></span>
    <span class="fa fa-star" id="star-3"></span>
    <span class="fa fa-star" id="star-4"></span>
    <span class="fa fa-star" id="star-5"></span>
    {{/renderStars}}
</div>

Then in my app.js file:

Handlebars.registerHelper('renderStars', (rating) => {
  for (let i = 0; i <= rating - 1; i++) {
    return new Handlebars.SafeString("<span class='fa fa-star checked'></span>");
  };
});

Finally a snippet of the context JSON data being passed to Handlebars template:

[
  {
    "month": "January",
    "image": "/images/sapiens.jpg",
    "altText": "Sapiens: A Brief History of Humankind, book by Yuval Noah Harari",
    "title": "Sapiens: A Brief History of Humankind",
    "author": "Yuval Noah Harari",
    "rating": 5,
},

Solution

  • "I've tried using jQuery [...] But I get a null value when searching for that element."

    You need to wait until the stars are appended to the DOM, before doing that.

    Regarding your for loop, it will only execute one iteration, since you return (end the function) during the first iteration.

    You could try this:

    Handlebars.registerHelper('renderStars', (rating) => {
      let result = '';
      for (let i = 1; i <= 5; i++) {
        let checked = rating >= i ? ' checked' : '';
        result += `<span class='fa fa-star${checked}'></span>`;
      }
      return new Handlebars.SafeString(result);
    });