Değişkenleri gidonlardan geçirme kısmi


131

Şu anda bir express.js uygulamasında handlebars.js ile uğraşıyorum. İşleri modüler tutmak için, tüm şablonlarımı bölümlere ayırıyorum.

Benim sorunum : Değişkenleri kısmi bir çağrı yoluyla geçirmenin bir yolunu bulamadım. Diyelim ki şuna benzeyen bir kısmım var:

<div id=myPartial>
    <h1>Headline<h1>
    <p>Lorem ipsum</p>
</div>

Bu kısmı 'myPartial' adıyla kaydettiğimi varsayalım. Başka bir şablonda şöyle bir şey söyleyebilirim:

<section>
    {{> myPartial}}
</section>

Bu iyi çalışıyor, kısmi beklendiği gibi işlenecek ve mutlu bir geliştiriciyim. Ama şimdi ihtiyacım olan şey, bu çağrı aracılığıyla farklı değişkenleri geçirmenin, örneğin bir başlık verilip verilmediğini kısmi olarak kontrol etmenin bir yolu. Gibi bir şey:

<div id=myPartial>
    {{#if headline}}
    <h1>{{headline}}</h1>
    {{/if}}
    <p>Lorem Ipsum</p>
</div>

Ve çağırma şunun gibi görünmelidir:

<section>
    {{> myPartial|'headline':'Headline'}}
</section>

ya da öylesine.

Bir şablonu oluşturmadan önce ihtiyacım olan tüm verileri tanımlayabileceğimi biliyorum. Ama açıkladığım gibi bunu yapmanın bir yolunu bulmalıyım. Olası bir yol var mı?

Yanıtlar:


214

Gidon parçaları, kısmi için bağlam haline gelen ikinci bir parametre alır:

{{> person this}}

V2.0.0 alfa ve sonraki sürümlerde, adlandırılmış parametrelerin bir karmasını da iletebilirsiniz:

{{> person headline='Headline'}}

Bu senaryolara yönelik testleri görebilirsiniz: https://github.com/wycats/handlebars.js/blob/ce74c36118ffed1779889d97e6a2a1028ae61510/spec/qunit_spec.js#L456-L462 https://github.com/wycats/handlebars.js/ damla / e290ec24f131f89ddf2c6aeb707a4884d41c3c6d / spec / partials.js # L26-L32


5
Bunun senaryonuz için nasıl geçerli olacağı hemen belli değil mi? Çözümü bir yere yazabilir misiniz - kendi durumunuza uygulayınız, lütfen? Teşekkürler!
serverman

12
@Yehuda Katz içeri geçmek yerine thiskendi bağlamınızda geçebilir misiniz? Örneğin, iletilecek ek verileri tanımlayın, örneğin {new_variable: some_data}?
Tri Nguyen

22
"Bu" u geçme yeteneğine sahip olmak güzel olsa da, her zaman yeterli değildir. Çoğunlukla, potansiyel olarak aynı sayfada belirli bir html parçasını yeniden kullanmak istersiniz, ancak parçanın kimlikleri varsa, mahkum olursunuz ... aynı kimlik birden fazla görünecek ve geçersiz hale gelecektir. İçeriğini daha da özelleştirmek için, onu çağırırken argümanları kısmi değerlere geçirebilmeniz son derece yararlı olacaktır.
Xavier_Ex

2
Gidon'un hangi sürümü bunu destekliyor? 1.3.0 kullanıyorum ve json üzerinden geçmeye çalışırken bir derleme hatası var{{> partialName {new_variable: some_data} }}
bafromca

1
@bafromca, tam olarak problemi, keyfi verileri ancak tek bir nesneyi iletemezsiniz. Yani ya bunu iletirsiniz ya da denetleyicide veya görünümde json verilerinizi döndüren yeni bir özellik yaratırsınız. İkincisi, keyfi verileri kısmi şeklinde iletmenin mümkün olması gerektiğini düşünüyorum key=value. Bunu github'da kapsayan herhangi bir sorun var mı?
ohcibi

18

Her ihtimale karşı, işte kısmi argümanlar elde etmek için yaptığım şey, bir nevi. Kısmi bir ad ve kısmi parametrelere aktarılacak küçük bir yardımcı oluşturdum:

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

Buradaki kilit nokta, Gidon yardımcılarının Ruby benzeri bir argüman karmasını kabul etmeleridir . Yardımcı kodunda onlar işlevin son argument- parçası olarak gelen options- onun içinde hashüyesi. Bu şekilde ilk bağımsız değişkeni - kısmi adı - alabilir ve bundan sonra verileri alabilirsiniz.

Daha sonra, muhtemelen Handlebars.SafeStringyardımcıdan bir geri döndürmek veya {{{çift ​​kaçışını önlemek için "üçlü zula" - - kullanmak istersiniz .

İşte aşağı yukarı eksiksiz bir kullanım senaryosu:

<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>

Umarım bu ... birine yardımcı olur. :)


15

Kendi yardımcınızı yazarsanız bu çok mümkündür. $Bu tür bir etkileşimi (ve daha fazlasını) gerçekleştirmek için özel bir yardımcı kullanıyoruz :

/*///////////////////////

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

1
Aktarılan bağımsız değişkenlere erişim sağlamak için, onları 'hash' nesnesinde aramanız gerekir: {{hash.foo}}. (Gidon konusunda yeniyim ve bunu anlamam biraz zaman aldı) - Teşekkürler, büyük yardımcı!
Claudio Bredfeldt

Bu, yardımcıyı kullanmadan önce parçalarınızı önceden derlemenizi gerektirir. Node.js'de Gidon kullanıyorum ve bunun her zaman böyle olmadığını buldum (parçalar talep üzerine derlendi). Parçalar yüklendikten sonra önceden derlemek için basit bir yardımcı eklemek zorunda kaldım, sonra bu harika çalıştı!
Dan

@Dan bu yardımcıyı paylaşma şansın var mı? :)
Tom

1
@Tom, İşte burada (güzelce nasıl biçimlendirileceğini anlayamıyorum, üzgünüm):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]); } }; }
Dan

@Dan Muhtemelen kendi cevabı olarak eklemek daha iyi.
alex

14

Bu aynı zamanda gidonların sonraki sürümlerinde key=valuegösterim kullanılarak da yapılabilir :

 {{> mypartial foo='bar' }}

Kısmi bağlamınıza belirli değerleri aktarmanıza izin verir.

Referans: Kısmi # 182 için bağlam farklı


1
Bu, v2.0.0 alfa sürümünden itibaren mevcuttur
Kevin Borders

9

Kabul edilen cevap, sadece kendi kısmınızda farklı bir bağlam kullanmak istiyorsanız harika çalışıyor. Ancak, herhangi bir ana bağlama başvurmanıza izin vermez. Birden fazla argüman iletmek için kendi yardımcınızı yazmanız gerekir. İşte Gidonlar için çalışan bir yardımcı 2.0.0(diğer cevap sürümler için geçerlidir <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) );
});

Ardından şablonunuzda aşağıdaki gibi bir şey yapabilirsiniz:

{{renderPartial 'myPartialName' foo=this bar=../bar}}

Ve kısmi olarak, bu değerlere aşağıdaki gibi bağlam olarak erişebileceksiniz:

<div id={{bar.id}}>{{foo}}</div>

Bu sürümü Handlebars 1.0.0 ile denedim ve kusursuz bir şekilde çalıştı.
Christopher Lörken

Bu, '...' adlı kısmi bir kısmı nerede 'arar'?
kemagezien

8

Böyle bir şey yapmak istiyor gibisin:

{{> person {another: 'attribute'} }}

Yehuda size bunu yapmanın bir yolunu zaten verdi:

{{> person this}}

Ancak açıklığa kavuşturmak için:

Kısmınıza kendi verilerini vermek için, ona mevcut model içinde kendi modelini vermeniz yeterlidir, örneğin:

{{> person this.childContext}}

Başka bir deyişle, şablonunuza verdiğiniz model buysa:

var model = {
    some : 'attribute'
}

Ardından parçaya verilecek yeni bir nesne ekleyin:

var model = {
    some : 'attribute',
    childContext : {
        'another' : 'attribute' // this goes to the child partial
    }
}

childContextYehuda'nın dediği gibi kısmi olanın bağlamı haline gelir - bunda, yalnızca alanı görür another, ancak görmez (veya alanı umursamaz some). idEn üst seviye modele sahipseniz idve childContext'te tekrarladıysanız , bu, sadece kısmen içeride ne olduğunu gördüğünden gayet iyi çalışacaktır childContext.



1

Bunun yardımcı olup olmadığından emin değilim, ancak burada bir satır içi RadioButtons kısmına kısmi geçirilen ve istemcinin (tarayıcı) kapsayıcıdaki radyo düğmelerini oluşturan dinamik parametrelere sahip bir Gidon şablonu örneği verilmiştir.

Benim kullanımım için, sunucuda Gidon ile işleniyor ve müşterinin bunu bitirmesine izin veriyor. Bununla birlikte, bir form aracı, gidonun içinde yardımcılar olmadan satır içi verileri sağlayabilir.

Not: Bu örnek jQuery gerektirir

{{#*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"}]' 
}}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.