Reputation: 2550
I am trying to build up an HTML that is going to be used in a jQuery Cycle carousel plugin that my end users want to use for a product carousel. The plugin requires the HTML to look like this:
<div id="slide-0"><!-- anything in here --></div>
<div id="slide-1"><!-- anything in here --></div>
<div id="slide-2"><!-- anything in here --></div>
<!-- etc. -->
However, the number of products is dynamic. In this case, it's coming from a JSON object like this:
JSON
var productJsonResponse = {
"products": [{
"Name": "Bulb"
},
{
"Name": "Wrench"
},
{
"Name": "Hammer"
},
{
"Name": "Screwdriver"
},
{
"Name": "Pliers"
}]
}
This is the Handlebars template I would like to build. I can't use the default {{#each}}
helper, since I need to create the outer "slide" divs. {{#createCarouselSlides}}
is a custom helper where the end user enters the number of slides he/she wants to create.
Template
{{#createCarouselSlides 2 products}}
<div id="slide-{{@index}}">
{{#customFunctionInner 2 ??? products}}
<div class="product">
<span class="product-name">{{Name}}</span>
</div>
{{/customFunctionInner}}
</div>
{{/createCarouselSlides}}
I figured out how to create the outer div part using a custom helper and looking at the Handlebars source code about how {{#each}}
works. But, I am unsure how to pass {{@index}}
into an inner custom function (customFunctionInner) where I need to segment my products. For example, if there are 5 products, and the end user wants 2 products per slide, I'll generate 3 slides, but I need the index to be able to know which products go into which slide.
Outer Helper
<script type="text/javascript">
; (function ($, Handlebars, window, document, undefined) {
Handlebars.registerHelper('createCarouselSlides', function (productsPerSlide, context, options) {
var result = "",
data = {};
// Create the necessary number of slides and populate them with the products in $products.
for (i = 0; i < Math.ceil(context.length / productsPerSlide); i += 1) {
data.index = i;
result += options.fn(context[i], { data: data });
}
return result;
});
})(jQuery, Handlebars, window, document);
</script>
My question is: Can I take {{@index}}
from my first helper and simply pass it into another custom helper? And what is the syntax look like?
This would be normally "easy" to do in plain Javascript as a pair of outer (i) and inner (j) for loops, where the outer loop controls the generation of the slide divs and passes i to the inner loop.
Upvotes: 1
Views: 1959
Reputation: 2550
I solved my problem. It required creating a private variable for the index in the outer helper and accessing it in the inner helper, via options.data.index. Since the inner helper is associated with a child template, the inner helper has access to the variable.
Template
{{#createCarouselSlides 2 products}}
<div id="slide-{{@index}}">
{{#createCarouselItemr 2 ../products}}
<div class="product">
<span class="product-name">{{Name}}</span>
</div>
{{/createCarouselItem}}
</div>
{{/createCarouselSlides}}
Helpers
; (function ($, Handlebars, window, document, undefined) {
/* Outer function */
Handlebars.registerHelper('createCarouselSlides', function (productsPerSlide, context, options) {
var result = "";
/* Create the necessary number of slides */
for (var i = 0; i < Math.ceil(context.length / productsPerSlide); i += 1) {
if (options.data) {
data = Handlebars.createFrame(options.data || {});
data.index = i;
}
result += options.fn(context[i], { data: data });
}
return result;
});
/* Inner Function */
Handlebars.registerHelper('createCarouselItem', function (productsPerSlide, context, options) {
var result = "",
currentItemIndex = "";
/* Create the necessary number of items per slide */
for (var j = 0; j < productsPerSlide; j += 1) {
currentItemIndex = (options.data.index * productsPerSlide) + j;
if (currentItemIndex < context.length) {
result += options.fn(context[currentItemIndex]);
}
}
return result;
});
})(jQuery, Handlebars, window, document);
Upvotes: 2