web-dev-qa-db-fra.com

Comment ajouter un séparateur entre les éléments d'une boucle {{#each}} sauf après le dernier élément?

J'ai un modèle de guidon dans lequel j'essaie de générer une liste d'éléments séparés par des virgules à partir d'un tableau.

Dans mon modèle de guidon:

{{#each list}}
    {{name}} {{status}},
{{/each}}

Je veux le , pour ne pas apparaître sur le dernier élément. Existe-t-il un moyen de le faire dans les guidons ou dois-je recourir à des sélecteurs CSS?

UPDATE : D'après la suggestion de Christopher, voici ce que j'ai fini par implémenter:

var attachments = Ember.CollectionView.extend({
    content: [],
    itemViewClass: Ember.View.extend({
        templateName: 'attachments',
        tagName: 'span',
        isLastItem: function() {
            return this.getPath('parentView.content.lastObject') == this.get('content');
        }.property('parentView.content.lastObject').cacheable()
    })
}));

et à mon avis:

{{collection attachments}}

et la vue de l'élément:

{{content.title}} ({{content.size}}) {{#unless isLastItem}}, {{/unless}}
55
Chris Thompson

Vous pouvez utiliser du CSS standard pour ce faire:

li:after {
    content: ',';
}

li:last-of-type:after {
    content: '';
}

Je préfère des règles séparées, mais une version plus concise mais légèrement moins lisible (de @Jay dans les commentaires):

li:not(:last-of-type):after {
    content: ',';
}
51

Je sais que je suis en retard pour les parties mais j'ai trouvé une méthode plus simple WAYYYY

{{#unless @last}},{{/unless}}
121
MylesBorins

Depuis Ember v1.11, vous pouvez obtenir l'index de chacun en utilisant les paramètres de bloc. Dans votre cas, cela ressemblerait à ceci:

{{#each list as |item index|}}
    {{if index ", "}}{{item.name}} {{item.status}}
{{/each}}

La première valeur de index sera 0 qui sera évalué à false et ne sera pas ajouté, toutes les valeurs suivantes seront évaluées à true qui ajoutera un séparateur.

56
Nahkala

Je me rends compte que c'est un an mais j'ai eu un problème similaire et je me suis retrouvé ici. Dans mon cas, je faisais face à un tableau. Alors, voici ma solution.

Handlebars.registerHelper('csv', function(items, options) {
    return options.fn(items.join(', '));
});

// then your template would be
{{#csv list}}{{this}}{{/csv}}

J'allais pour une solution simple et élégante qui conserve la logique csv dans le modèle.

5
freak3dot

J'ai créé un assistant de bloc sep:

Handlebars.registerHelper("sep", function(options){
    if(options.data.last) {
        return options.inverse();
    } else {
        return options.fn();
    }
});

Usage:

{{#each Data}}
   {{Text}}{{#sep}},{{/sep}}
{{/each}}

Prend en charge la déclaration else.

4
Jadro007

Avec ember 2.7 vous pouvez le faire après avoir installé ember-truth-helpers:

ember install ember-truth-helpers

puis votre modèle ressemblera à ceci:

{{#each model as |e|}}
    {{e}}{{#unless (eq e model.lastObject)}}, {{/unless}}
{{/each}}
4
albertjan

J'ai obtenu ce travail avec une version modifiée de la réponse de freak3dot:

handlebars.registerHelper('csv', function(items, options) {
  return items.map(function(item) {
    return options.fn(item)
  }).join(', ')
})

(Ceci est une application de nœud, alors changez le map en conséquence pour souligner ou peu importe si vous construisez dans le navigateur)

Permet de formater des objets entre chaque virgule:

{{#csv players}
  {{firstName}} {{lastName}}
{{/csv}}

Edit: voici une version plus flexible. Joignez une liste de choses sur un séparateur arbitraire.

handlebars.registerHelper('join', function(items, separator, options) {
  return items.map(function(item) {
    return options.fn(item)
  }).join(separator)
})

Et modèle:

{{#join players ' vs '}
  {{firstName}} {{lastName}}
{{/join}}
3
mmacaulay

Peut-être que dans ce contexte, vous devriez créer une vue pour la collection, pas une itération de vues sur les éléments membres. Dans ce cas, un itérateur de guidon est exagéré. Dans mon exemple ci-dessous, les modifications apportées à firstName ou lastName sur les objets Person seront liées à la liste et mettront à jour la vue.

Modèle:

{{App.listController.csv}}

Javascript:

App = Ember.Application.create();

var Person = Ember.Object.extend({
    firstName: null,
    lastName: null
});

var bob = Person.create({
    firstName: "bob",
    lastName: "smith"
});

var ann = Person.create({
    firstName: "ann",
    lastName: "doe"
});

App.listController = Ember.Object.create({
    list: [bob, ann],
    csv: Ember.computed(function () {
        var arr = [];
        this.get('list').forEach(function (item, index, self) {
            arr.Push(item.firstName + ' ' + item.lastName);
        })
        return arr.join(',');
        }).property('[email protected]', '[email protected]')
});
// any changes to bob or ann will update the view
bob.set('firstName', 'tim');
// adding or removing from the array will update the view
App.listController.get('list').pushObject(Person.create(firstName: "Jack", lastName:"Dunn"});

Ci-dessous est ma réponse originale, qui n'a pas fonctionné dans ce contexte.

Vous devriez pouvoir le faire avec un assistant:

Handlebars.registerHelper('csv', function(items, options) {
  var out = "";
  for(var i=0, l=items.length; i<l; i++) {
    out += options.fn(items[i]);
    if (i < l - 1) {
        out += ',';
    }
    // might want to add a newline char or something
  } 
  return out;
});

// then your template would be
{{#csv list}} {{name}} {{status}} {{/each}}
2
hellslam