Setang / Moustache - Apakah ada cara dibangun untuk loop melalui properti dari suatu objek?

216

Seperti judul pertanyaan mengatakan, apakah ada cara kumis / setang perulangan melalui properti objek ?

Begitu juga dengan

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

Lalu bisakah saya melakukan sesuatu di mesin templat yang akan setara dengan

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

?

Ben
sumber

Jawaban:

448

Dukungan bawaan sejak Setang 1.0rc1

Dukungan untuk fungsi ini telah ditambahkan ke Handlebars.js, sehingga tidak perlu lagi untuk bantuan eksternal.

Bagaimana cara menggunakannya

Untuk array:

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

Untuk benda:

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

Perhatikan bahwa hanya properti yang lulus hasOwnPropertytes yang akan disebutkan.

Jon
sumber
2
@Rafi: orang tidak bisa memahaminya tanpa mengetahui struktur data Anda.
Jon
3
@Rafi: bukankah maksud Anda {{this.title}}?
nevyn
2
@qodeninja: Sederhana: cara yang sama Anda merujuk ke nilai-nilai dalam contoh di atas - dengan {{#each this}}. Pilihan istilah Anda juga membingungkan (apa yang membuat satu objek "tingkat atas" dan yang lain tidak? Apa sebenarnya kunci "yang ditentukan sebelumnya" dll?), Sehingga Anda mungkin ingin meninjau kembali konsep-konsep ini.
Jon
1
jika tidak salah maka hanya dengan v1.1.0 ini tersedia, tetapi jawaban yang bagus terima kasih.
Renars Sirotins
2
Bagaimana Anda melakukan ini hanya untuk daftar putih properti tertentu?
Marco Prins
70

Sebenarnya cukup mudah diterapkan sebagai pembantu:

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

Kemudian gunakan seperti ini:

{{#eachProperty object}}
    {{property}}: {{value}}<br/>
{{/eachProperty }}
Ben
sumber
2
Terlihat bagus, apakah Anda perlu menambahkan tanda centang hasOwnProperty di dalam loop agar Anda tidak mengulangi properti prototipe?
monkeyboy
Solusi hebat @Ben. Jika ada yang mencoba menggunakan ini dengan Ember, lihat jawaban saya di bawah ini untuk solusi agar bisa berfungsi.
flynfish
27

EDIT: Setang sekarang memiliki cara untuk mencapai ini; lihat jawaban yang dipilih di atas. Ketika bekerja dengan Kumis biasa, di bawah ini masih berlaku.

Moustache dapat mengulangi item dalam array. Jadi saya sarankan membuat objek data terpisah yang diformat dengan cara Kumis dapat bekerja dengan:

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

Sekarang, template Moustache Anda akan menjadi seperti:

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

Lihat bagian "Daftar Non-Kosong" di sini: https://github.com/janl/mustache.js

Amit
sumber
1
Akhirnya pergi dengan saran Anda karena saya harus melewati beberapa sub properti tambahan pula. Terima kasih untuk bantuannya!
Ben
Terima kasih banyak, ide Anda menyelamatkan saya hari lain mencari alternatif. Baris ini adalah kumis kunciFormattedData = {'people': []};
Matt
Bagaimana Anda melakukan ini dengan array objek "o"?
red888
4

Ini adalah jawaban @ Ben yang diperbarui untuk digunakan dengan Ember ... catatan yang harus Anda gunakan Ember.get karena konteks dilewatkan sebagai String.

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

Templat:

{{#eachProperty object}}
  {{key}}: {{value}}<br/>
{{/eachProperty }}
flynfish
sumber
Terima kasih @flynfish. konteks adalah string di Ember ?? sepertinya .. agak aneh.
Ben
Ya saya tidak begitu yakin karena saya baru mengenal Ember dan masih berusaha menemukan jalan saya untuk mengatasinya.
flynfish
1

@ Amit jawaban baik karena akan bekerja di Moustache dan Setang.

Sejauh solusi khusus Handlebars, saya telah melihat beberapa dan saya suka each_with_keypembantu blok di https://gist.github.com/1371586 yang terbaik.

  • Ini memungkinkan Anda untuk beralih pada objek literal tanpa harus merestrukturisasi mereka terlebih dahulu, dan
  • Ini memberi Anda kendali atas apa yang Anda sebut variabel kunci. Dengan banyak solusi lain, Anda harus berhati-hati dalam menggunakan kunci objek yang diberi nama 'key', atau 'property', dll.
mjumbewu
sumber
Temuan yang bagus. Hanya peringatan bagi pembaca lain: helper "key_value" di intisari ini memiliki bug di dalamnya. Baca komentar untuk cara memperbaikinya.
sirentian
0

Terima kasih atas solusi Ben, kasus penggunaan saya hanya menampilkan bidang tertentu secara berurutan

dengan objek

Kode:

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

Sumber objek:

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

Templat:

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

Keluaran:

locationDesc --- abc
description --- def
name --- ghi
vincentlcy
sumber
0

Ini adalah fungsi pembantu untuk mustacheJS, tanpa memformat data sebelumnya dan sebaliknya mendapatkannya saat render.

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

Templat:

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

Keluaran:

color: blue
color: red

(pesanan mungkin acak - ini peta) Ini mungkin berguna jika Anda tahu elemen peta yang Anda inginkan. Berhati-hatilah dengan nilai-nilai palsu.

Cuel
sumber
-1

Saya menggunakan versi lama 1.0.beta.6dari setang, saya pikir di suatu tempat selama 1.1 - 1.3 fungsi ini ditambahkan, jadi memperbarui ke 1.3.0 memecahkan masalah, ini adalah penggunaannya:

Pemakaian:

{{#each object}}
  Key {{@key}} : Value {{this}}
{{/people}}
AamirR
sumber