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.