Obecnie mam do czynienia z handlebars.js w aplikacji express.js. Aby zachować modułowość, dzielę wszystkie moje szablony na części.
Mój problem : nie mogłem znaleźć sposobu na przekazanie zmiennych przez częściowe wywołanie. Powiedzmy, że mam częściową, która wygląda tak:
<div id=myPartial>
<h1>Headline<h1>
<p>Lorem ipsum</p>
</div>
Załóżmy, że zarejestrowałem tę część pod nazwą „myPartial”. W innym szablonie mogę wtedy powiedzieć coś takiego:
<section>
{{> myPartial}}
</section>
To działa dobrze, częściowe będą renderowane zgodnie z oczekiwaniami i jestem szczęśliwym programistą. Ale to, czego teraz potrzebuję, to sposób na przekazywanie różnych zmiennych przez to wywołanie, aby na przykład sprawdzić w części, czy podano nagłówek, czy nie. Coś jak:
<div id=myPartial>
{{#if headline}}
<h1>{{headline}}</h1>
{{/if}}
<p>Lorem Ipsum</p>
</div>
A wywołanie powinno wyglądać mniej więcej tak:
<section>
{{> myPartial|'headline':'Headline'}}
</section>
lub tak.
Wiem, że jestem w stanie zdefiniować wszystkie potrzebne mi dane, zanim wyrenderuję szablon. Ale potrzebuję sposobu, aby to zrobić, jak właśnie wyjaśniono. Czy jest możliwy sposób?
źródło
this
mówić, czy mógłbyś podać swój własny kontekst. Na przykład zdefiniuj dodatkowe dane do przekazania, takie jak{new_variable: some_data}
?{{> partialName {new_variable: some_data} }}
key=value
. Czy jest jakiś problem dotyczący tego w Github?Na wszelki wypadek oto co zrobiłem, aby uzyskać częściowe argumenty. Stworzyłem małego pomocnika, który przyjmuje częściową nazwę i skrót parametrów, które zostaną przekazane do części:
Handlebars.registerHelper('render', function(partialId, options) { var selector = 'script[type="text/x-handlebars-template"]#' + partialId, source = $(selector).html(), html = Handlebars.compile(source)(options.hash); return new Handlebars.SafeString(html); });
Kluczową rzeczą jest to, że pomocnicy Handlebars akceptują hash argumentów podobny do Rubiego . W kodzie pomocniczym pojawiają się jako część ostatniego argumentu funkcji
options
- - w jej składnikuhash
. W ten sposób możesz otrzymać pierwszy argument - częściową nazwę - a następnie pobrać dane.Następnie prawdopodobnie zechcesz zwrócić
Handlebars.SafeString
pomocnikowi lub użyć „potrójnego skrytki” -{{{
-, aby zapobiec podwójnemu ucieczce.Oto mniej lub bardziej kompletny scenariusz użycia:
<script id="text-field" type="text/x-handlebars-template"> <label for="{{id}}">{{label}}</label> <input type="text" id="{{id}}"/> </script> <script id="checkbox-field" type="text/x-handlebars-template"> <label for="{{id}}">{{label}}</label> <input type="checkbox" id="{{id}}"/> </script> <script id="form-template" type="text/x-handlebars-template"> <form> <h1>{{title}}</h1> {{ render 'text-field' label="First name" id="author-first-name" }} {{ render 'text-field' label="Last name" id="author-last-name" }} {{ render 'text-field' label="Email" id="author-email" }} {{ render 'checkbox-field' label="Private?" id="private-question" }} </form> </script>
Mam nadzieję, że to pomoże… komuś. :)
źródło
Jest to bardzo możliwe, jeśli napiszesz własnego pomocnika. Używamy niestandardowego
$
pomocnika do realizacji tego typu interakcji (i nie tylko):/*/////////////////////// Adds support for passing arguments to partials. Arguments are merged with the context for rendering only (non destructive). Use `:token` syntax to replace parts of the template path. Tokens are replace in order. USAGE: {{$ 'path.to.partial' context=newContext foo='bar' }} USAGE: {{$ 'path.:1.:2' replaceOne replaceTwo foo='bar' }} ///////////////////////////////*/ Handlebars.registerHelper('$', function(partial) { var values, opts, done, value, context; if (!partial) { console.error('No partial name given.'); } values = Array.prototype.slice.call(arguments, 1); opts = values.pop(); while (!done) { value = values.pop(); if (value) { partial = partial.replace(/:[^\.]+/, value); } else { done = true; } } partial = Handlebars.partials[partial]; if (!partial) { return ''; } context = _.extend({}, opts.context||this, _.omit(opts, 'context', 'fn', 'inverse')); return new Handlebars.SafeString( partial(context) ); });
źródło
hbs.registerPartials(path.join(__dirname, '/views/partials'), function() { utils.precompileHandlebarsPartials(hbs); }); // Pre compile the partials precompileHandlebarsPartials : function(hbs) { var partials = hbs.handlebars.partials; for (var partial in partials) { if (typeof partials[partial] === 'string') { partials[partial] = hbs.handlebars.compile(partials[partial]); } }; }
Można to również zrobić w późniejszych wersjach kierownic, używając
key=value
notacji:{{> mypartial foo='bar' }}
Umożliwienie przekazania określonych wartości do częściowego kontekstu.
Odniesienie: inny kontekst dla części nr 182
źródło
Zaakceptowana odpowiedź działa świetnie, jeśli chcesz po prostu użyć innego kontekstu w części. Jednak nie pozwala ci odwołać się do żadnego kontekstu nadrzędnego. Aby przekazać wiele argumentów, musisz napisać własnego pomocnika. Oto działający pomocnik dla
2.0.0
kierownic (druga odpowiedź działa dla wersji<2.0.0
):Handlebars.registerHelper('renderPartial', function(partialName, options) { if (!partialName) { console.error('No partial name given.'); return ''; } var partial = Handlebars.partials[partialName]; if (!partial) { console.error('Couldnt find the compiled partial: ' + partialName); return ''; } return new Handlebars.SafeString( partial(options.hash) ); });
Następnie w swoim szablonie możesz zrobić coś takiego:
{{renderPartial 'myPartialName' foo=this bar=../bar}}
Po części będziesz mieć dostęp do tych wartości jako kontekstu, takiego jak:
źródło
Wygląda na to, że chcesz zrobić coś takiego:
{{> person {another: 'attribute'} }}
Yehuda dał ci już sposób na zrobienie tego:
{{> person this}}
Ale żeby wyjaśnić:
Aby nadać częściowi własne dane, po prostu nadaj jej własny model w istniejącym modelu, na przykład:
{{> person this.childContext}}
Innymi słowy, jeśli to jest model, który dajesz swojemu szablonowi:
var model = { some : 'attribute' }
Następnie dodaj nowy obiekt, który ma być podany do części:
var model = { some : 'attribute', childContext : { 'another' : 'attribute' // this goes to the child partial } }
childContext
staje się kontekstem częściowości, jak powiedział Yehuda - w tym widzi tylko poleanother
, ale nie widzi (lub nie dba o polesome
). Jeśli miałeśid
model najwyższego poziomu i powtórz toid
ponownie w childContext, to zadziała dobrze, ponieważ część widzi tylko to, co jest w środkuchildContext
.źródło
Tak, spóźniłem się, ale mogę dodać dla użytkowników Assemble : możesz użyć wbudowanego
"parseJSON"
pomocnika http://assemble.io/helpers/helpers-data.html . (Odkryte na https://github.com/assemble/assemble/issues/416 ).źródło
Nie jestem pewien, czy jest to pomocne, ale oto przykład szablonu Handlebars z dynamicznymi parametrami przekazywanymi do wbudowanej części RadioButtons i klientem (przeglądarką) renderującym przyciski radiowe w kontenerze.
Do mojego użytku jest renderowany za pomocą Handlebars na serwerze i pozwala klientowi dokończyć proces. Dzięki niemu narzędzie do formularzy może udostępniać dane wbudowane w kierownicy bez pomocy.
Uwaga: ten przykład wymaga jQuery
{{#*inline "RadioButtons"}} {{name}} Buttons<hr> <div id="key-{{{name}}}"></div> <script> {{{buttons}}}.map((o)=>{ $("#key-{{name}}").append($('' +'<button class="checkbox">' +'<input name="{{{name}}}" type="radio" value="'+o.value+'" />'+o.text +'</button>' )); }); // A little test script $("#key-{{{name}}} .checkbox").on("click",function(){ alert($("input",this).val()); }); </script> {{/inline}} {{>RadioButtons name="Radio" buttons='[ {value:1,text:"One"}, {value:2,text:"Two"}, {value:3,text:"Three"}]' }}
źródło