Manubri / Baffi: esiste un modo integrato per scorrere le proprietà di un oggetto?


216

Come dice il titolo della domanda, c'è un modo baffi / manubrio di scorrere un proprietà di oggetto ?

Quindi con

var o = {
  bob : 'For sure',
  roger: 'Unknown',
  donkey: 'What an ass'
}

Posso quindi fare qualcosa nel motore di modello che sarebbe equivalente

for(var prop in o)
{
    // with say, prop a variable in the template and value the property value
}

?

Risposte:


448

Supporto integrato da Manubrio 1.0rc1

Il supporto per questa funzionalità è stato aggiunto a Handlebars.js, quindi non è più necessario un aiuto esterno.

Come usarlo

Per array:

{{#each myArray}}
    Index: {{@index}} Value = {{this}}
{{/each}}

Per gli oggetti:

{{#each myObject}}
    Key: {{@key}} Value = {{this}}
{{/each}}

Si noti che hasOwnPropertyverranno enumerate solo le proprietà che superano il test.


2
@Rafi: non si può capire molto senza conoscere la struttura dei dati.
Jon

3
@Rafi: non intendi {{this.title}}?
nevyn,

2
@qodeninja: Semplice: allo stesso modo in cui ti riferisci ai valori negli esempi sopra - con {{#each this}}. Anche la scelta dei termini è confusa (cosa rende un oggetto "di livello superiore" e un altro no? Cosa sono esattamente le chiavi "predefinite", ecc.), Quindi potresti voler rivisitare questi concetti.
Jon,

1
se non si sbaglia allora solo con v1.1.0 questo è disponibile, ma un'ottima risposta grazie.
Renars Sirotins,

2
Come si fa solo per una specifica lista bianca di proprietà?
Marco Prins,

70

In realtà è abbastanza facile da implementare come aiuto:

Handlebars.registerHelper('eachProperty', function(context, options) {
    var ret = "";
    for(var prop in context)
    {
        ret = ret + options.fn({property:prop,value:context[prop]});
    }
    return ret;
});

Quindi usandolo così:

{{#eachProperty object}}
    {{property}}: {{value}}<br/>
{{/eachProperty }}

2
Sembra buono, è necessario aggiungere un controllo hasOwnProperty all'interno del ciclo in modo da non ripetere le proprietà del prototipo?
monkeyboy,

Ottima soluzione @Ben. Nel caso in cui qualcuno stia cercando di usarlo con Ember, vedi la mia risposta qui sotto per la soluzione per farlo funzionare.
flynfish

27

EDIT: il manubrio ora ha un modo integrato per raggiungere questo obiettivo; vedere la risposta selezionata sopra. Quando si lavora con semplici baffi, vale ancora il seguito.

I baffi possono scorrere gli elementi in un array. Quindi suggerirei di creare un oggetto dati separato formattato in modo che Moustache possa funzionare con:

var o = {
  bob : 'For sure',
  roger: 'Unknown',
  donkey: 'What an ass'
},
mustacheFormattedData = { 'people' : [] };

for (var prop in o){
  if (o.hasOwnProperty(prop)){
    mustacheFormattedData['people'].push({
      'key' : prop,
      'value' : o[prop]
     });
  }
}

Ora, il tuo modello di baffi sarebbe qualcosa del tipo:

{{#people}}
  {{key}} : {{value}}
{{/people}}

Consulta la sezione "Elenchi non vuoti" qui: https://github.com/janl/mustache.js


1
Alla fine ho seguito il tuo suggerimento in quanto ho bisogno di passare comunque alcune proprietà secondarie aggiuntive. Grazie per l'aiuto!
Ben

Grazie mille, la tua idea mi ha salvato un altro giorno in cerca di alternative. Questa riga è la chiave moustacheFormattedData = {'people': []};
Matt

Come faresti con una serie di oggetti "o"?
red888,

4

Questa è la risposta di @ Ben aggiornata per l'uso con Ember ... nota che devi usare Ember.getperché il contesto viene passato come stringa.

Ember.Handlebars.registerHelper('eachProperty', function(context, options) {
  var ret = "";
  var newContext = Ember.get(this, context);
  for(var prop in newContext)
  {
    if (newContext.hasOwnProperty(prop)) {
      ret = ret + options.fn({property:prop,value:newContext[prop]});
    }
  }
  return ret;
});

Modello:

{{#eachProperty object}}
  {{key}}: {{value}}<br/>
{{/eachProperty }}

Grazie @flynfish. il contesto è una stringa in Ember ?? sembra .. alquanto strano.
Ben

Sì, non ne sono davvero sicuro poiché sono nuovo di Ember e sto ancora cercando di orientarmi.
flynfish

1

La risposta di Amit è buona perché funzionerà sia con i baffi che con i manubri.

Per quanto riguarda le soluzioni solo per il manubrio, ne ho viste alcune e mi piace l' each_with_keyhelper di blocco su https://gist.github.com/1371586 il migliore.

  • Ti permette di iterare su oggetti letterali senza doverli prima ristrutturare, e
  • Ti dà il controllo su ciò che chiami la variabile chiave. Con molte altre soluzioni devi stare attento all'uso delle chiavi degli oggetti denominate 'key', o 'property', ecc.

Bella scoperta. Solo un avvertimento per gli altri lettori: l'helper "key_value" in questa sintesi contiene un bug. Leggi i commenti su come risolverlo.
Sirentian

0

Grazie per la soluzione di Ben, il mio caso d'uso per visualizzare solo determinati campi in ordine

con oggetto

Codice:

    handlebars.registerHelper('eachToDisplayProperty', function(context, toDisplays, options) {
    var ret = "";
    var toDisplayKeyList = toDisplays.split(",");
    for(var i = 0; i < toDisplayKeyList.length; i++) {
        toDisplayKey = toDisplayKeyList[i];
        if(context[toDisplayKey]) {
            ret = ret + options.fn({
                property : toDisplayKey,
                value : context[toDisplayKey]
            });
        }

    }
    return ret;
});

Oggetto sorgente:

   { locationDesc:"abc", name:"ghi", description:"def", four:"you wont see this"}

Modello:

{{#eachToDisplayProperty this "locationDesc,description,name"}}
    <div>
        {{property}} --- {{value}}
    </div>
    {{/eachToDisplayProperty}}

Produzione:

locationDesc --- abc
description --- def
name --- ghi

0

Questa è una funzione di supporto per moustacheJS, senza pre-formattazione dei dati e invece ottenerli durante il rendering.

var data = {
    valueFromMap: function() {
        return function(text, render) {
            // "this" will be an object with map key property
            // text will be color that we have between the mustache-tags
            // in the template
            // render is the function that mustache gives us

            // still need to loop since we have no idea what the key is
            // but there will only be one
            for ( var key in this) {
                if (this.hasOwnProperty(key)) {
                    return render(this[key][text]);
                }
            }
        };
    },

    list: {
        blueHorse: {
            color: 'blue'
        },

        redHorse: {
            color: 'red'
        }
    }
};

Modello:

{{#list}}
    {{#.}}<span>color: {{#valueFromMap}}color{{/valueFromMap}}</span> <br/>{{/.}}
{{/list}}

Uscite:

color: blue
color: red

(l'ordine potrebbe essere casuale - è una mappa) Questo potrebbe essere utile se conosci l'elemento mappa che desideri. Fai attenzione ai valori falsi.


-1

Stavo usando la vecchia versione 1.0.beta.6 del manubrio, penso che da qualche parte durante 1.1 - 1.3 sia stata aggiunta questa funzionalità, quindi l'aggiornamento alla 1.3.0 ha risolto il problema, ecco l'uso:

Uso:

{{#each object}}
  Key {{@key}} : Value {{this}}
{{/people}}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.