Mandalina
Mandalina

Reputation: 446

Generate new array using handlebars helper, and use new array in html

I currently pass an array of objects to a handlebars helper function to sort and return a new array. I want to use the new array to fill in my html.

My handlebars template is as follows:

  FoodGroup: [
    {
      name: "vegetables",
      foods: [
        {
          name: "celery",
          description: "lorem ipsum..."
        },
        {
          name: "cucumber",
          description: "lorem ipsum..."
        }
      ]
    },
    {
      name: "fruits",
      foods: [
        {
          name: "banana",
          description: "lorem ipsum..."
        },
        {
          name: "apple",
          description: "lorem ipsum..."
        }
      ]
    }
  ]

This is what my helper function looks like:

<script type="text/javascript">
    Handlebars.registerHelper("sortFood", function(items, options){
        var allFood = [];
        // iterate through each FoodGroup
        for (var i = 0; i < items.length; i++) {
            var seperatedArray = items[i].foods;
            // iterate through all foods within each group and push into allFood array
            for (var j = 0; j < seperatedArray.length; j++) {
                allFood.push(seperatedArray[j]);
            }
        }
        // sort all foods alphabetically
        allFood.sort(function(a,b){
            var textA = a.name.toLowerCase();
            var textB = b.name.toLowerCase();
            return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
        });

        // create new object for individual arrays for first letter of each food name
        var sortedFood = {};
        for (var i=0; i<allFood.length; i++) {
          var l = allFood[i].name.substring(0,1);
          // ensure object has key
          if (!sortedFood[l]) sortedFood[l] = [];
          sortedFood[l].push(allFood[i]);
        }

        console.log(sortedFood)

        return sortedFood;
    });

</script>

Currently I pass an array to the helper function like this

{{#sortFood FoodGroup}}
{{/sortFood}}

And the helper function returns a sorted object that looks like this. The helper takes the original object FoodGroup and pulls out all of the food objects and sorts it alphabetically in an array alphabetically:

sortedFood= {
  A: [
    {
      name: "Apple",
      description: "lorem ipsum ...."
    }
  ],
  B: [
    {
      name: "Banana",
      description: "lorem ipsum ...."
    }
  ],
  C: [
    {
      title: "Celery",
      summary: "lorem ipsum ...."      
    },
    {
      title: "Cucumber",
      summary: "lorem ipsum ...."      
    },
    {
      title: "Customer Surveys",
      summary: "lorem ipsum ...."      
    }
  ]
  .. etc   
}

I want to generate a list in my html that looks like this using the newly generated "sortedFoods" array from the handlebars helper

<h1>A</h1>
   <li>Apple</li>
<h1>B</h1>
   <li>Banana</li>
<h1>C</h1>
   <li>Celery</li>
   <li>Cucumber</li>

Upvotes: 1

Views: 4755

Answers (1)

Christophe
Christophe

Reputation: 2200

Here is the way to do that with handlebars. You can run the below snippet and check the code. The key is to use option.fn() to return your data and then you can use a template inside the call of your custom helper. To get the a,b,c labels you have to use the {{#each}} helper and the {{@key}} inside of it.

$(document).ready(function () {
  var context = {
      FoodGroup: [
    {
      name: "vegetables",
      foods: [
        {
          name: "celery",
          description: "lorem ipsum..."
        },
        {
          name: "cucumber",
          description: "lorem ipsum..."
        }
      ]
    },
    {
      name: "fruits",
      foods: [
        {
          name: "banana",
          description: "lorem ipsum..."
        },
        {
          name: "apple",
          description: "lorem ipsum..."
        }
      ]
    }
  ]
  };
    Handlebars.registerHelper("sortFood", function(items, options){
        var allFood = [];
        // iterate through each FoodGroup
        for (var i = 0; i < items.length; i++) {
            var seperatedArray = items[i].foods;
            // iterate through all foods within each group and push into allFood array
            for (var j = 0; j < seperatedArray.length; j++) {
                allFood.push(seperatedArray[j]);
            }
        }
        // sort all foods alphabetically
        allFood.sort(function(a,b){
            var textA = a.name.toLowerCase();
            var textB = b.name.toLowerCase();
            return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
        });

        // create new object for individual arrays for first letter of each food name
        var sortedFood = {};
        for (var i=0; i<allFood.length; i++) {
          var l = allFood[i].name.substring(0,1);
          // ensure object has key
          if (!sortedFood[l]) sortedFood[l] = [];
          sortedFood[l].push(allFood[i]);
        }

        //console.log(sortedFood)

        return options.fn(sortedFood);
    });
	var source   = $("#sourceTemplate").html();
  var template = Handlebars.compile(source);
  var html    = template(context);
  $("#resultPlaceholder").html(html);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script id="sourceTemplate" type="text/x-handlebars-template">
{{#sortFood FoodGroup}}
  {{#each this}}
    <h1>{{@key}}</h1>
    {{#each this}}
      <ul>
        <li>{{name}}</li>
        <li>{{description}}</li>
      </ul>
    {{/each}}
  {{/each}}
{{/sortFood}}
</script>
<br/>
<div id="resultPlaceholder">
</div>

Upvotes: 2

Related Questions