Handlebars Template Çözümü
Handlebars, Mustache şablon dilini benimseyen hafif bir template çözümüdür. Handlebars, çıkış noktasını Javascript diliyle sağlasa da, farklı programlama dilleri için yazılan kütüphaneler de mevcuttur. Eğer daha önceden Mustache ile ilgili bilginiz yok ise, bu bağlantıdan Mustache yazımızı okuyabilirsiniz.
Javascript ortamındaki template çözümlerinin temel maksadı, bir javascript nesnesi ile bir text veriyi çarpıştırmak ve sonucunda çözümlenmiş bir çıktı üretmektir.
Handlebars, Mustache’da olduğu gibi ikişer tane süslü parantez {{..}}arasında yer alan yer tutuculara sahiptir. İkili mustache yerine üçlüsü de {{{..}}}mevcuttur. Bu yer tutucular, tanımlı isim bilgisine göre Javascript nesnesinden aldığı verilerle giydirilerek çıktı olarak sunulmaktadır. İkili mustache ifadeleri, “<" ve ">” karakterlerini “<” ve “>” olarak çözümlerken (escaped), üçlü mustache ise bu dönüşümü sunmamaktadır (non-escaped).
Örnek 1: Basit Başlangıç örneği olarak aşağıdaki, HTML biçimindeki text şablonunu referans alalım.
<script id="book" type="text/x-handlebars-template">
<div class="panel panel-primary">
<div class="panel-body">
<p>{{name}}</p>
<p>{{author}}</p>
<p>{{price}}</p>
</div>
</div>
</script>
Bu text şablonda, 3 adet yer tutucu yer almaktadır. name, author ve price. Bu yer tutucular örneğin bu isimdeki alanlara sahip bir Javascript nesnesi ile doldurulabilirdir. Fakat giydirme işleminden önce, template verisi Handlebars tarafından compile edilmelidir. Handlebars bir text şablonu derledikten sonra ortaya bir Javascript fonksiyonu çıkarmaktadır. Çıkarılan bu fonksiyon tekrar tekrar aynı şablonu kullanma olanağı sunmaktadır. Hatta bu şablonlar, Javascript ortamındaki çeşitli araçlarla önceden derlenerek, çalışma anındaki derlenme maliyeti ortadan kaldırılabilmektedir.
var template = $("#book").html();
var compiled = Handlebars.compile(template);
Handlebars nesnesi, Handlebars javascript bağımlılığının sunduğu bir nesnedir. Handlebars.compile(..) fonksiyonu ile de şablon ifade derlenmektedir. Derleme sonucunda ise, bir Javascript fonksiyonu geri döndürülmektedir. Döndürülen Js fonksiyonu ise, parametre olarak gönderilen context nesnesi aracılığıyla, şablon ve nesneyi giydirerek bir String çıktı üretmektedir.
var book = {};
book.name="Java ve Yazılım Tasarımı";
book.author="Altuğ B. Altıntaş";
book.price=34;
var result = compiled(book);
Örneğin üretilen bu fonksiyon aşağıdaki book nesnesiyle giydirilebilirdir. compiled değişkenine book nesnesi paslandığında, result değişkeni içerisinde içerisi giydirilmiş çıktı oluşmaktadır. Aşağıdaki JSBin çıktıdan üretilen sonucu inceleyebilirsiniz.
Örnek 2: each Helper Mustache’da olduğu gibi Handlebars da Javascript dizi nesnelerini döngüsel olarak üretebilmektedir. Bu maksatla “each” isminde bir Helper ifadeye sahiptir. Handlebars ile kendi Helper ifadelerinizi de oluşturabileceğinizi şimdiden belirtmek isterim. Helper ifadeler aralıksız veya aralıklı olarak tanımlanabilmektedir.
Aralıksız ifadeler;
{{helper_name param1 param2 paramN}} şeklinde tanımlanırken,
Aralıklı ifadeler ise;
{{#helper_name param1 param2 paramN}} … {{/helper_name}}
Handlebars ile döngüsel işlemleri kullanmayı sağlayan “each” ifadesi ise, Aralıklı ifadeler kısmına girmektedir.
<script id="book" type="text/x-handlebars-template">
<div class="panel panel-primary">
<div class="panel-body">
<ul>
{{#each this}}
<li>{{name}} / {{{author}}} / {{price}}</li>
{{/each}}
</ul>
</div>
</div>
</script>
“each” deyimi tek bir parametre almaktadır. Alacağı parametre ise, bir Javascript dizisine karşılık gelmelidir. Burada belirtilen this ifadesi, o andaki context alanına adanan nesneyi temsil etmektedir. this deyimi yerine istenirse . (Nokta) da kullanılabilmektedir. this ifadesine karşılık gelecek Js nesnesi ise, içerisinde 4 Js nesnesi barındıran aşağıdaki Js dizisidir.
var books = [
{
name:"Java ve Yazılım Tasarımı",
author:"<b>Altuğ Altıntaş</b>",
price:34
},
{
name:"Java Mimarisiyle Kurumsal Çözümler",
author:"<b>Rahman Usta</b>",
price:25
},
{
},
{
}];
“each” deyimli şablon ve Js dizisi çarpıştırıldığında aşağıdaki çıktı üretilmektedir.
Örnek 3:Partials Handlebars ile birden fazla şablon verisini parçalı olarak bütünleştirebiliriz. Parçalı şablonlar {{> partial_name}} deyimiyle referans verilirken, Handlebars.registerPartial(..) fonksiyonu ile de uygulamaya deklare edilmektedir.
<script id="book" type="text/x-handlebars-template">
<div class="panel panel-primary">
<div class="panel-body">
<table class="table table-responsive">
<thead><tr>
<th>ID</th><th>Book name</th><th>Book author</th><th>Book Price</th>
</tr></thead>
<tbody>
{{> rows}} {{! Bu bir yorum satırıdır.}}
</tbody>
</table>
</div>
</div>
</script>
<script id="rows" type="text/x-handlebars-template">
{{#each this}}
<tr>
<td>{{@index}}</td><td><b>{{name}}</b></td><td>{{{author}}}</td><td>{{price}}</td>
</tr>
{{/each}}
</script>
Yukarıda yer alan table elemanının tbody kısmında “rows” isimli parçaya referans verildiği görülebilir.
var books = [
{
name:"Java ve Yazılım Tasarımı",
author:"Altuğ B. Altıntaş",
price:34
},
{
name:"Java Mimarisiyle Kurumsal Çözümler",
author:"Rahman Usta",
price:undefined
}];
Handlebars.registerPartial("rows",$("#rows").html());
var template = $("#book").html();
var compiled = Handlebars.compile(template);
var result = compiled(books);
Örnek 4: if Helper Örnek 4 içindeki bir nesnenin “price” alanı undefined olarak belirtilmiştir. Eğer belirli bir alanın true/false değerine göre çözümleme sağlanmak isteniyorsa Handlebars “if” deyimi kullanılabilir. “if” deyimine verilen parametre true ise ({}, true, 1,10 gibi) aralığın içerisindeki veriler çözümlenmekte, false ise (null, undefined, 0, false, “”, -16 gibi) çözümlenmemektedir.
<script id="rows" type="text/x-handlebars-template">
{{#each this}}
{{#if this.price}}
<tr>
<td>{{@index}}</td>
<td><b>{{name}}</b></td>
<td>{{{author}}}</td>
<td>{{price}}</td>
</tr>
{{/if}}
{{/each}}
</script>
“rows” şablonu “if” helper ile düzenlendiğinde “price” alanı falsy değer içerdiği için, o anki nesne için tablo satırı üretilmemektedir.
Örnek 5: each-else “each” helper, bir dizi ile döngüsel olarak çıktı üretmektedir. Eğer adanan Js nesnesi boş olması durumunda farklı bir çıktı üretilmek isteniyorsa, “each” aralığında {{else}} helper kullanılabilmektedir. {{else}} helper “if” helper ile de benzer biçimde kullanılabilmektedir.
{{#each this}}
<tr><td><b>{{name}}</b></td><td>{{{author}}}</td><td>{{price}}</td></tr>
{{else}}
<tr><td colspan="3">Henüz kayıt yok</td></tr>
{{/each}}
Örnek6: SubContext Handlebars ile bir nesne ağacının alt ve üst elemanlarına erişilebilmektedir. Subcontext için . (Nokta) kullanılırken, Supercontext için ../ ifadeleri kullanılmaktadır.
var book = {
name:"Java ve Yazılım Tasarımı",
author:"Altuğ B. Altıntaş",
price:34,
content:[]
};
book.content.push("Kalıtım");
book.content.push(undefined);
book.content.push("MultiThreading");
book.content.push(null);
book.content.push("Çokyüzlülük");
book.content.push(0);
book.content.push("Ağ programlama");
book.content.push(false);
var template = $("#book").html();
var compiled = Handlebars.compile(template);
var result = compiled(book);
Örneğin yukarıda yer alan “book” nesnesinin “content” alanındaki diziye erişilmek isteniyorsa, aşağıdaki şekliyle kullanılabilir.
<script id="book" type="text/x-handlebars-template">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">
{{name}} / <b>{{author}}</b> / {{price}}
</h3>
</div>
<div class="panel-body">
<ul>
{{#each this.content}}
<li>{{.}}</li>
{{/each}}
</ul>
</div>
</div>
</script>
Örnek7: SubContext Örnek 6 içerisindeki, falsy değerler listelemeden süzülmek isteniyorsa, “if” deyimi kullanılabilir. Handlebars içinde “if” deyimine zıt olarak işleyen “unless” deyimi de yer almaktadır.
<script id="book" type="text/x-handlebars-template">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">
{{name}} / <b>{{author}}</b> / {{price}}
</h3>
</div>
<div class="panel-body">
<ul>
{{#each content}}
{{#if .}} {{! Dikkat this veya .}}
<li>{{.}}</li>
{{/if}}
{{/each}}
</ul>
</div>
</div>
</script>
Örnek 8:Custom Helper Handlebars if, each, unless helper ifadeleri gibi kendi helper deyimleri tanımlayabilmenize de olanak tanımaktadır. Örneğin, if deyimi true/false çıktısına göre içerisinde barındırdığı ifadeleri çözümlemektedir. Fakat if deyiminin 2 ifadeyi karşılaştırma gibi bir fonksiyonu yoktur. Fakat siz kendi helper deyimlerinizi bu istikamette yapılandırabilirsiniz.
var model = [
{
key:1,
value:"Ali",
},
{
key:2,
value:"Veli",
},
{
key:3,
value:"Selami",
},
{
key:2,
value:"Elif",
},
{
key:2,
value:"Kerim",
},
{
key:3,
value:"Murat",
}];
Örneğin yukarıda yer alan Javascript dizisinde, key alanı “2” olan isimlerin listelenmesi isteniyor olsun. Bu karşılaştırma için aşağıda yer alan “ifeq” deyimi özel olarak tanımlanabilir.
Handlebars.registerHelper("ifeq",function(val1,val2,opt){
return (val1 == val2) ? opt.fn(this) : '';
});
“ifeq” helper deyimi 2 parametre alacağı için aşağıdaki gibi kullanılabilir.
<ol>
{{#each this}}
{{#ifeq key "2"}}
<li>{{key}} -> {{value}}</li>
{{/ifeq}}
{{/each}}
</ol>
Tekrar görüşmek dileğiyle..
Tag:frontend, handlebars, template