¿Hay una forma integrada de recorrer las propiedades de un objeto?

5 minutos de lectura

avatar de usuario
ben

¿Hay alguna forma de bigote / manillar de recorrer un objeto ¿propiedades?

Así que con

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

¿Puedo entonces hacer algo? en el motor de plantillas eso equivaldría a

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

?

Soporte incorporado desde Handlebars 1.0rc1

Soporte para esta funcionalidad ha sido añadido a Handlebars.js, por lo que ya no hay necesidad de ayudantes externos.

Cómo usarlo

Para arreglos:

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

Para objetos:

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

Tenga en cuenta que solo las propiedades que pasan el hasOwnProperty se enumerará la prueba.

  • @Rafi: sin embargo, uno no puede tener mucho sentido sin conocer su estructura de datos.

    – Jon

    22 de julio de 2013 a las 18:11

  • @Rafi: ¿No querrás decir {{this.title}}?

    – Nevyn

    17 de octubre de 2013 a las 9:43

  • @qodeninja: Simple: de la misma manera que se refiere a los valores en los ejemplos anteriores, con {{#each this}}. Su elección de términos también es confusa (¿qué hace que un objeto sea de “nivel superior” y otro no? ¿Qué son exactamente las claves “predefinidas”? etc.), por lo que es posible que desee revisar estos conceptos.

    – Jon

    11 de febrero de 2014 a las 9:42

  • si no se equivoca, solo está disponible con v1.1.0, pero excelente respuesta, gracias.

    – Renars sirotinas

    1 de julio de 2015 a las 14:23

  • ¿Cómo hace esto solo para una lista blanca específica de propiedades?

    – Marco Prins

    28 de julio de 2015 a las 14:43

avatar de usuario
ben

En realidad, es bastante fácil de implementar como ayudante:

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

Luego usándolo así:

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

  • Se ve bien, ¿necesita agregar una verificación hasOwnProperty dentro del bucle para no iterar sobre las propiedades del prototipo?

    – Chico mono

    28 de noviembre de 2012 a las 11:26

  • Gran solución @Ben. En caso de que alguien intente usar esto con Ember, vea mi respuesta a continuación para ver la solución para que funcione.

    – pez volador

    29 mayo 2013 a las 19:54

avatar de usuario
amit

EDITAR: Handlebars ahora tiene una forma integrada de lograr esto; ver la respuesta seleccionada arriba. Cuando se trabaja con Moustache simple, se aplica lo siguiente.

Moustache puede iterar sobre los elementos de una matriz. Por lo tanto, sugeriría crear un objeto de datos separado formateado de manera que Moustache pueda funcionar 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]
     });
  }
}

Ahora, su plantilla de bigote sería algo como:

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

Consulte la sección “Listas no vacías” aquí: https://github.com/janl/mustache.js

  • Terminé yendo con su sugerencia ya que necesito pasar algunas subpropiedades adicionales de todos modos. ¡Gracias por la ayuda!

    – ben

    30 de enero de 2012 a las 11:28

  • Muchas gracias, tu idea me salvó otro día de buscar alternativas. Esta línea es la clave mustacheFormattedData = { ‘personas’: [] };

    – Mate

    02/09/2013 a las 15:17


  • ¿Cómo harías esto con una matriz de objetos “o”?

    – rojo888

    25/09/2014 a las 19:49

avatar de usuario
pez volador

Esta es la respuesta de @Ben actualizada para usar con Ember … tenga en cuenta que debe usar Ember.get porque el contexto se pasa como una cadena.

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;
});

Modelo:

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

La respuesta de @Amit es buena porque funcionará tanto en Moustache como en Handlebars.

En cuanto a las soluciones solo para manubrios, he visto algunas y me gusta la each_with_key ayudante de bloque en https://gist.github.com/1371586 lo mejor.

  • Le permite iterar sobre literales de objetos sin tener que reestructurarlos primero, y
  • Le da control sobre lo que llama la variable clave. Con muchas otras soluciones, debe tener cuidado al usar claves de objeto denominadas 'key'o 'property'etc.

  • Buen hallazgo Solo una advertencia para otros lectores: el ayudante “key_value” en esta esencia tiene un error. Lea los comentarios para saber cómo solucionarlo.

    – sirentiano

    25 de octubre de 2012 a las 7:48


avatar de usuario
vicente

Gracias por la solución de Ben, mi caso de uso para mostrar solo campos particulares en orden

con objeto

Código:

    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;
});

Objeto fuente:

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

Modelo:

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

Producción:

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

  • Buen hallazgo Solo una advertencia para otros lectores: el ayudante “key_value” en esta esencia tiene un error. Lea los comentarios para saber cómo solucionarlo.

    – sirentiano

    25 de octubre de 2012 a las 7:48


Esta es una función de ayuda para mustacheJS, sin formatear previamente los datos y, en cambio, obtenerlos durante el renderizado.

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'
        }
    }
};

Modelo:

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

Salidas:

color: blue
color: red

(el orden puede ser aleatorio, es un mapa) Esto podría ser útil si conoce el elemento del mapa que desea. Solo tenga cuidado con los valores falsos.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad