Je tire parti de handlebars.js pour mon moteur de templates et cherche à faire afficher un segment conditionnel uniquement s'il s'agit du dernier élément du tableau contenu dans l'objet de configuration de modèles.
{
columns: [{<obj>},{<obj>},{<obj>},{<obj>},{<obj>}]
}
J'ai déjà fait appel à un assistant pour effectuer des comparaisons égalité/supérieur/inférieur à et j'ai réussi à identifier l'élément initial de cette façon mais je n'ai pas eu la chance d'accéder à la longueur de mon tableau cible.
Handlebars.registerHelper('compare', function(lvalue, rvalue, options) {...})
"{{#each_with_index columns}}"+
"<div class='{{#equal index 0}} first{{/equal}}{{#equal index ../columns.length()}} last{{/equal}}'>"+
"</div>"+
"{{/each_with_index}}"
Est-ce que quelqu'un connaît un raccourci, une approche différente et quelques avantages du guidon qui m'empêcheront de devoir déchirer le moteur de guidons.js pour déterminer la meilleure trajectoire?
Depuis Handlebars v1.1.0, vous pouvez désormais utiliser les booléens
@first
et@last
dans chaque aide pour résoudre ce problème:
{{#each foo}}
<div class='{{#if @first}}first{{/if}}
{{#if @last}} last{{/if}}'>
{{@key}} - {{@index}}
</div>
{{/each}}
Un assistant rapide que j'ai écrit pour faire le tour est:
Handlebars.registerHelper("foreach",function(arr,options) {
if(options.inverse && !arr.length)
return options.inverse(this);
return arr.map(function(item,index) {
item.$index = index;
item.$first = index === 0;
item.$last = index === arr.length-1;
return options.fn(item);
}).join('');
});
Ensuite, vous pouvez écrire:
{{#foreach foo}}
<div class='{{#if $first}} first{{/if}}{{#if $last}} last{{/if}}'></div>
{{/foreach}}
Depuis Handlebars 1.1.0, first et last sont devenus natifs pour chaque aide. Voir billet # 483 .
L'utilisation est comme classe d'Eberanov helper:
{{#each foo}}
<div class='{{#if @first}}first{{/if}}{{#if @last}} last{{/if}}'>{{@key}} - {{@index}}</div>
{{/each}}
Si vous essayez simplement de gérer le premier élément du tableau, cela peut aider
{{#each data-source}}{{#if @index}},{{/if}}"{{this}}"{{/each}}
@index est fourni par chaque assistant et pour le premier élément, il est égal à zéro et peut donc être traité par l'assistant if.
Solution:
<div class='{{#compare index 1}} first{{/compare}}{{#compare index total}} last{{/compare}}'></div>
Tirer parti des aides du blog et de Gist suivants ...
https://Gist.github.com/2889952
http://doginthehat.com.au/2012/02/comparison-block-helper-for-handlebars-templates/
// {{#each_with_index records}}
// <li class="legend_item{{index}}"><span></span>{{Name}}</li>
// {{/each_with_index}}
Handlebars.registerHelper("each_with_index", function(array, fn) {
var total = array.length;
var buffer = "";
//Better performance: http://jsperf.com/for-vs-foreach/2
for (var i = 0, j = total; i < j; i++) {
var item = array[i];
// stick an index property onto the item, starting with 1, may make configurable later
item.index = i+1;
item.total = total;
// show the inside of the block
buffer += fn(item);
}
// return the finished buffer
return buffer;
});
Handlebars.registerHelper('compare', function(lvalue, rvalue, options) {
if (arguments.length < 3)
throw new Error("Handlerbars Helper 'compare' needs 2 parameters");
operator = options.hash.operator || "==";
var operators = {
'==': function(l,r) { return l == r; },
'===': function(l,r) { return l === r; },
'!=': function(l,r) { return l != r; },
'<': function(l,r) { return l < r; },
'>': function(l,r) { return l > r; },
'<=': function(l,r) { return l <= r; },
'>=': function(l,r) { return l >= r; },
'typeof': function(l,r) { return typeof l == r; }
}
if (!operators[operator])
throw new Error("Handlerbars Helper 'compare' doesn't know the operator "+operator);
var result = operators[operator](lvalue,rvalue);
if( result ) {
return options.fn(this);
} else {
return options.inverse(this);
}
});
Notez que l'index de départ est correctement 1.
J'ai apporté quelques améliorations à l'aide de Matt Brennan , vous pouvez utiliser cette aide avec Objects ou Arrays, cette solution nécessite la bibliothèque Underscore :
Handlebars.registerHelper("foreach", function(context, options) {
options = _.clone(options);
options.data = _.extend({}, options.hash, options.data);
if (options.inverse && !_.size(context)) {
return options.inverse(this);
}
return _.map(context, function(item, index, list) {
var intIndex = _.indexOf(_.values(list), item);
options.data.key = index;
options.data.index = intIndex;
options.data.isFirst = intIndex === 0;
options.data.isLast = intIndex === _.size(list) - 1;
return options.fn(item, options);
}).join('');
});
Usage:
{{#foreach foo}}
<div class='{{#if @first}}first{{/if}}{{#if @last}} last{{/if}}'>{{@key}} - {{@index}}</div>
{{/foreach}}