Kierownice / wąsy - Czy istnieje wbudowany sposób na przeglądanie właściwości obiektu?

216

Jak mówi tytuł pytania, czy istnieje sposób zapętlania wąsów / kierownicy przez właściwości obiektu ?

Więc z

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

Czy mogę zrobić coś w silniku szablonów, co byłoby równoważne

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

?

Ben
źródło

Odpowiedzi:

448

Wbudowane wsparcie od Kierownicy 1.0rc1

Obsługa tej funkcjonalności została dodana do Handlebars.js, więc nie ma już potrzeby korzystania z zewnętrznych pomocników.

Jak tego użyć

W przypadku tablic:

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

Dla obiektów:

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

Zauważ, że hasOwnPropertywyliczone zostaną tylko właściwości zaliczające test.

Jon
źródło
2
@Rafi: nie można tego jednak zrozumieć bez znajomości struktury danych.
Jon
3
@Rafi: nie masz na myśli {{this.title}}?
Nevyn
2
@qodeninja: Proste: w ten sam sposób odwołujesz się do wartości w powyższych przykładach - za pomocą {{#each this}}. Twój wybór terminów jest również mylący (co powoduje, że jeden obiekt jest „najwyższym poziomem”, a inny nie? Czym dokładnie są „wstępnie zdefiniowane” klucze? Itp.), Więc możesz chcieć ponownie zapoznać się z tymi pojęciami.
Jon
1
jeśli się nie pomyli, to tylko z wersją 1.1.0 jest to dostępne, ale świetna odpowiedź dzięki.
Renars Sirotins
2
Jak to zrobić tylko dla określonej białej listy właściwości?
Marco Prins,
70

W rzeczywistości jest bardzo łatwy do wdrożenia jako pomocnik:

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

Następnie użyj go w ten sposób:

{{#eachProperty object}}
    {{property}}: {{value}}<br/>
{{/eachProperty }}
Ben
źródło
2
Wygląda dobrze, czy musisz dodać kontrolę pętli hasOwnProperty w pętli, aby nie powtarzać właściwości prototypu?
monkeyboy
Świetne rozwiązanie @Ben. W przypadku, gdy ktoś próbuje użyć tego z Ember, zapoznaj się z moją odpowiedzią poniżej, aby uzyskać rozwiązanie umożliwiające jego uruchomienie.
Flynfish
27

EDYCJA: Kierownica ma teraz wbudowany sposób na osiągnięcie tego; patrz wybrana odpowiedź powyżej. Podczas pracy z zwykłym wąsem nadal obowiązują poniższe zasady.

Wąsy mogą iterować elementy w tablicy. Sugeruję więc utworzenie osobnego obiektu danych sformatowanego w sposób, w jaki wąs może współpracować z:

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

Teraz twój szablon Wąsy byłby podobny do:

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

Sprawdź sekcję „Niepuste listy” tutaj: https://github.com/janl/mustache.js

Amit
źródło
1
Skończyło się na twojej sugestii, ponieważ i tak muszę przekazać dodatkowe właściwości podrzędne. Dzięki za pomoc!
Ben
Dzięki bardzo, twój pomysł uratował mi kolejny dzień szukania alternatyw. Ten wiersz jest kluczowym wąsemFormattedData = {'people': []};
Matt
Jak zrobiłbyś to z tablicą obiektów „o”?
red888
4

To jest odpowiedź @ Ben zaktualizowana do użytku z Ember ... Uwaga: musisz jej użyć, Ember.getponieważ kontekst jest przekazywany jako ciąg.

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

Szablon:

{{#eachProperty object}}
  {{key}}: {{value}}<br/>
{{/eachProperty }}
mucha
źródło
Dzięki @flynfish. kontekst to ciąg znaków w Ember? to wydaje się ... trochę dziwne.
Ben
Tak, nie jestem do końca pewien, ponieważ jestem nowy w Ember i wciąż próbuję znaleźć sposób na obejście tego.
Flynfish
1

Odpowiedź Amita jest dobra, ponieważ będzie działać zarówno w wąsach, jak i kierownicach.

Jeśli chodzi o rozwiązania tylko dla kierownic, widziałem kilka i najbardziej podoba mi się each_with_keypomocnik bloku na https://gist.github.com/1371586 .

  • Umożliwia iterację literałów obiektowych bez konieczności ich wcześniejszej restrukturyzacji, oraz
  • Daje ci kontrolę nad tym, co nazywasz zmienną kluczową. Z wieloma innymi rozwiązaniami trzeba być ostrożnym przy użyciu klawiszy obiekt o nazwie 'key'lub 'property'itp
mjumbewu
źródło
Niezłe znalezisko. Tylko ostrzeżenie dla innych czytelników: pomocnik „wartość_klucza” w tej liście zawiera błąd. Przeczytaj komentarze, jak to naprawić.
sirentian
0

Dzięki za rozwiązanie Bena, mój przypadek użycia wyświetla tylko określone pola w kolejności

z przedmiotem

Kod:

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

Obiekt źródłowy:

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

Szablon:

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

Wynik:

locationDesc --- abc
description --- def
name --- ghi
Vincentlcy
źródło
0

Jest to funkcja pomocnicza dla programu mustacheJS, bez wstępnego formatowania danych i pobierania ich podczas renderowania.

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

Szablon:

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

Wyjścia:

color: blue
color: red

(kolejność może być losowa - to mapa) Może to być przydatne, jeśli znasz element mapy, który chcesz. Uważaj tylko na wartości fałszowania.

Cuel
źródło
-1

Użyłem starej wersji 1.0.beta.6 kierownicy, myślę, że gdzieś podczas 1.1 - 1.3 ta funkcjonalność została dodana, więc aktualizacja do 1.3.0 rozwiązała problem, oto użycie:

Stosowanie:

{{#each object}}
  Key {{@key}} : Value {{this}}
{{/people}}
AamirR
źródło