Estoy usando Bigote y uso de los datos

{ "names": [ {"name":"John"}, {"name":"Mary"} ] }

Mi bigote plantilla:

{{#names}}
    {{name}}
{{/names}}

Lo que quiero ser capaz de hacer es conseguir un índice de la cantidad actual en la matriz. Algo así como:

{{#names}}
    {{name}} is {{index}}
{{/names}}

y tienen que imprimir

John is 1
Mary is 2

Es posible conseguir esto con Bigote? o con el Manillar o en otra extensión?

  • Se ejecuta en O(n) tiempo de… Mustache.render('{{#list}}{{index}}{{/list}}', { list: ['a', 'b', 'c' ], index: () => (++this.i || (this.i = 0)) });

12 Comentarios

  1. 31

    De referencia, esta funcionalidad está ahora integrado en el Manillar que tiene compatibilidad con Bigote.

    Uso {{@index}}

    {{#names}}
        {{name}} is {{@index}}
    {{/names}}
    

    Juan es 0

    María es de 1

    • Yay! Finalmente, a pesar de que en los proyectos que terminó usando el código está utilizando el nativo de android y objc bigote bibliotecas. Por tanto, no podemos utilizar el JavaScript Manillar más. Pero esto se ve como una gran alternativa.
    • Manillar de ser compatible con bigote es un error común. El manillar NO ES compatible con bigote a todos. Ellos no son intercambiables en todos. Sólo quería aclarar que debido a que quedó atrapado tratando de usar uno para el otro.
    • Esto no funciona para mí. ¿Es para usted?
    • Es allí cualquier manera de hacerlo sólo con bigote ?
    • El manillar NO ES compatible con bigote a todos. Aunque dicen que este en su sitio web es completamente falso.
    • Esto no debería ser aceptado como respuesta que no responde a la pregunta del título.
    • Esta es una terrible respuesta. Bigote no es específico de la plataforma, mientras que el Manillar es.

  2. 48

    Esta es la forma en que yo lo hago en JavaScript:

    var idx = 0;
    
    var data = { 
       "names": [ 
           {"name":"John"}, 
           {"name":"Mary"} 
        ],
        "idx": function() {
            return idx++;
        }
    };
    
    var html = Mustache.render(template, data);
    

    Su plantilla:

    {{#names}}
        {{name}} is {{idx}}
    {{/names}}
    
    • El problema con esto es que usted tiene que recordar que sólo alguna vez el idx vez, de lo contrario va a cambiar para el objeto actual. En algunas de nuestras plantillas, utilizamos el índice en más de una ubicación para el objeto actual.
    • gran respuesta y he añadido una solución para múltiples {{idx}}
    • La solución para varios {{index}} se puede encontrar en Índice de un elemento de matriz en Mustache.js @oyatek
    • Yo uso en mi plantilla de vista a una función que devuelve el índice de uso de indexOf, consulte mi respuesta para más detalles.
  3. 13

    En handlebars.js usted puede lograr esto con una función auxiliar. (De hecho, una de las ventajas mencionadas sobre el manillar aquí http://yehudakatz.com/2010/09/09/announcing-handlebars-js/ es que usted puede utilizar ayudantes en lugar de tener que reescribir los objetos antes de llamar a la plantilla.

    Es así, usted podría hacer esto:

      var nameIndex = 0;
      Handlebars.registerHelper('name_with_index', function() {
        nameIndex++;
        return this.name + " is " + nameIndex;
      })
    

    Y, a continuación, la plantilla puede ser este:

    {{#names}}
    <li>{{name_with_index}}</li>
    {{/names}}
    

    Sus datos es el mismo de antes, es decir:

    { "names": [ {"name":"John"}, {"name":"Mary"} ] };
    

    Y se obtiene este resultado:

    <li>John is 1</li>
    <li>Mary is 2</li>
    

    Para hacer realidad este trabajo, nameIndex necesita obtener restablece cada vez que la plantilla se representa, lo que puede tener un restablecimiento de auxiliar al comienzo de la lista. Así, el código completo se parece a esto:

      var data = { "names": [ {"name":"John"}, {"name":"Mary"} ] };
      var templateSource = "<ul>{{reset_index}}{{#names}}<li>{{name_with_index}}</li>{{/names}}</ul>";
      var template = Handlebars.compile(templateSource);
    
      var helpers = function() {
        var nameIndex = 0;
        Handlebars.registerHelper('name_with_index', function() {
          nameIndex++;
          return this.name + " is " + nameIndex;
        });
        Handlebars.registerHelper('reset_index', function() {
          nameIndex = 0;
        })
      }();
    
      var htmlResult= template(data);
      $('#target').html(htmlResult);
    
      var htmlResult2= template(data);
      $('#target2').html(htmlResult2);
    

    (Esto puede procesa correctamente la plantilla dos veces).

    • Que podría funcionar, aunque tiene el problema de que no se puede utilizar el índice en más de un sitio durante el artículo. Ya que cada vez que recuperar el índice se incrementa. Esto no funciona bien para los diseñadores de plantillas y hará que los errores y problemas. También, con la «reset_index», añade en una lógica método para restablecer el índice, que creo que va de nuevo la logicless plantillas. He visto en la versión de Android que tienen disponible {{ -índice}} lo que hace la cosa correcta.
  4. 7

    Puede ejecutar el siguiente bucle en su lista de objetos.

    Esta solución tiene las siguientes ventajas:

    • No cambia el modelo de datos
    • El índice se puede acceder varias veces

    Código:

    for( var i=0; i< the_list.length; i++) {
        the_list[i].idx = (function(in_i){return in_i+1;})(i);
    }
    

    Explicación:

    Una función se utiliza en lugar de un nombre de variable, por lo que los datos no está mutado. El cierre se utiliza para devolver el valor de » i » en el momento en que se crea la función en el bucle en lugar de el valor de i, al final del bucle.

    • Esto es genial, gracias!
  5. 6

    Un mejor enfoque para Bigote sería el uso de una función que obtiene el índice de uso de indexOf:

    var data = { 
       names: [ {"name":"John"}, {"name":"Mary"} ],
        index: function() {
            return data.names.indexOf(this);
        }
    };
    
    var html = Mustache.render(template, data);
    

    En su plantilla:

    {{#names}}
        {{name}} is {{index}}
    {{/names}}
    

    El inconveniente es que este index función de la matriz codificada data.names para hacerla más dinámica, podemos utilizar otra función como esta:

    var data = { 
       names: [ {"name":"John"}, {"name":"Mary"} ],
        index: function() {
            return function(array, render) {
                return data[array].indexOf(this);
            }
        }
    };
    
    var html = Mustache.render(template, data);
    

    Uso en su plantilla:

    {{#names}}
        {{name}} is {{#index}}names{{/index}}
    {{/names}}
    

    También un pequeño inconveniente es que tienes que pasar el nombre de la matriz a la función indice en este ejemplo names, {{#index}}names{{/index}}.

    • Otro problema es que este algoritmo es O(N^2), lo que podría causar problemas de tamaño moderado listas. Cada vez que usted obtiene el índice de un elemento, usted tiene que buscar en toda la lista.
  6. 4

    Gran ayuda aquí:

    //{{#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 buffer = "";
        for (var i = 0, j = array.length; 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;
    
            //show the inside of the block
            buffer += fn(item);
        }
    
        //return the finished buffer
        return buffer;
    
    });
    

    Fuente: https://gist.github.com/1048968

  7. 1

    Si usted puede controlar la salida de la cadena JSON, entonces trate de hacer esto.

    { "names": [ {"name":"John", "index":"1"}, {"name":"Mary", "index":"2"} ] }
    

    Así que cuando usted hace su cadena JSON, agregar el índice como otra de las propiedades de cada objeto.

    • ¿Hay alguna forma de hacerlo sin tener que agregar en el índice de propiedad de los datos? Los datos que yo estoy haciendo no lo tiene y me tome un subconjunto de ella. Tenía la esperanza de obtener un índice de forma gratuita.
    • No parece ser, por desgracia. Usted podría tratar de iterar sobre él en su JS antes de ejecutar las plantillas, y la adición de los índices de entonces. O echar un vistazo a la fuente y ver si se puede agregar algo para volver al índice actual.
    • Ok, voy a dejar esto abierto por un par de días para ver si hay alguna otra solución. De lo contrario voy a marcar este uno como correcta.
    • hay una solución mejor a continuación, usted debe cambiar su respuesta seleccionada
    • Cuál es la solución que usted se refiere? muchas de las otras soluciones (además de la ya soporte nativo en el Manillar para el índice) sólo permiten que el índice se recuperan una vez. Que no es una gran solución, especialmente desde que necesitamos para insertar el índice más de una vez en nuestras plantillas.
  8. 1

    Mi principal caso de uso para esta era la capacidad para realizar un ‘activo’ de la clase de elementos. He metido con la combinación de una «equivale a» auxiliar con y «index_for_each» helper, pero era demasiado complicado.

    Lugar, se me ocurrió de la siguiente manera «activa» helper. Es muy específico, pero es un caso de uso habitual para cualquier menú /seleccionar de la lista de escenario:

    Uso:

      <ul>
        {{{active 2}}}
        {{#each menuItem}}
          <li class="{{{active}}}">{{this}}</li>
        {{/each}}
      </div>
    

    Haría el 3er elemento de menú tiene una «clase=’activo'».

    El ayudante es aquí (este es el CoffeeScript versión):

    active = 0
    cur = 0
    handlebars.registerHelper 'active', (item, context) ->
      if arguments.length == 2
        active = item
        cur = 0
        ''
      else if cur++ == active
        'active'
    
  9. 1

    Mientras no estás viajando en más de una matriz puede almacenar el índice en la ayuda y sólo se incrementan cuando el contexto cambia. Estoy usando algo similar a la siguiente:

    var data = {
        foo: [{a: 'a', 'b': 'a'}, {'a':'b', 'b':'b'}], 
        i: function indexer() {
            indexer.i = indexer.i || 0;
            if (indexer.last !== this && indexer.last) {                                          
                indexer.i++;
            }   
            indexer.last = this;
            return String(indexer.i);
         }   
    };
    
    Mustache.render('{{#foo}}{{a}}{{i}}{{b}}{{i}}{{/foo}}', data);
    
  10. 1

    (Probado en el nodo 4.4.7, bigote 2.2.1.)

    Si quieres un bonito y limpio funcional manera de hacerlo, que no se trata de variables globales o de la mutación de los objetos en sí, el uso de esta función;

    var withIds = function(list, propertyName, firstIndex) {
        firstIndex |= 0;
        return list.map( (item, idx) => {
            var augmented = Object.create(item);
            augmented[propertyName] = idx + firstIndex;
            return augmented;
        })
    };
    

    Usar cuando estás en el montaje de su vista;

    var view = {
        peopleWithIds: withIds(people, 'id', 1) //add 'id' property to all people, starting at index 1
    };
    

    El bueno de este enfoque es que se crea un nuevo conjunto de «viewmodel» objetos, usando el antiguo conjunto de prototipos. Usted puede leer el person.id como lo haría leer person.firstName. Sin embargo, esta función no cambia su gente todos los objetos, por lo que otro tipo de código (que podría haber invocado el ID de la propiedad que no está allí) no se verán afectados.

    Algoritmo es O(N), de forma agradable y rápida.

  11. 0

    Solución Recomendada


    Mi recomendación es agregar un index clave

    let data = { "names": [ {"name":"John"}, 
    {"name":"Mary"} ] };
    
    //Add an index manually
    data = {
      names: [
        { id: 0, name: "John" },
        { id: 1, name: "Mary" }
      ]
    };
    
    //Add an index with a loop
    data = data.names
      .map(function (name, i) {
        name.id = i;
        return name;
      });
    
    //Nested arrays with indices (parentId, childId)
    data = {
      names: [{
        parentId: 0,
        name: "John",
        friends: [{
          childId: 0,
          name: "Mary"
        }]
      }]
    };
    

    Otras soluciones propuestas no son tan limpios, y sufre de bastantes problemas como se detalla a continuación.


    Problemas con la propuesta de Bigote Índice soluciones


    @Índice

    Bigote no admite @Índice

    IndexOf

    Esta solución se ejecuta en O(n^2), y por tanto no tiene el mejor rendimiento. También el índice debe ser creado manualmente para cada lista.

    const data = {
      list: ['a', 'b', 'c'],
      listIndex: function () {
        return data.list.indexOf(this);
      }
    };
    
    Mustache.render('{{#list}}{{listIndex}}{{/list}}', data);
    

    Variable Global

    Esta solución se ejecuta en O(n) tiempo, así que mejor rendimiento, pero también se «contamina el espacio global» (es decir, las propiedades agregadas a la window objeto, no obtienen la basura que se recoge hasta que se cierra la ventana del navegador), y el índice debe ser creado manualmente para cada lista.

    const data = {
      list: ['a', 'b', 'c'],
      listIndex: function () {
        return (++window.listIndex || (window.listIndex = 0));
      }
    };
    
    Mustache.render('{{#list}}{{listIndex}}{{/list}}', data);
    

    Variable Local

    Esta solución se ejecuta en O(n) tiempo, no «contaminar el espacio global», y no necesita ser creado manualmente para cada lista. Sin embargo, la solución es compleja y no funciona bien con listas anidadas.

    const data = {
      listA: ['a', 'b', 'c'],
      index: () => name => (++data[`${name}Index`] || (data[`${name}Index`] = 0))
    };
    
    Mustache.render('{{#listA}}{{#index}}listA{{/index}}{{/listA}}', data);
    
  12. 0
    <script>var index = 1;</script>
    {{#names}}
        {{name}} is <script>document.write(index++);</script>
    {{/names}}
    

    Esto funciona perfectamente bien.

    • Que tipo de derrotas el propósito de Bigote.

Dejar respuesta

Please enter your comment!
Please enter your name here