web-dev-qa-db-fra.com

conditionnel sur le dernier élément du tableau à l'aide du modèle handlebars.js

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?

60
techie.brandon

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}}
89
matt brennan

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}}
150
Jacob van Lingen

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.

25
Yong Qu

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.

1
techie.brandon

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}}
0
ebaranov