Membuat template dengan Setang

1. Ikhtisar

Dalam tutorial ini, kita akan melihat pustaka Handlebars.java untuk manajemen template yang mudah.

2. Ketergantungan Maven

Mari kita mulai dengan menambahkan ketergantungan setang :

 com.github.jknack handlebars 4.1.2 

3. Template Sederhana

Template Handlebars dapat berupa file teks apa pun. Ini terdiri dari tag seperti {{name}} dan {{#each people}}.

Kemudian kami mengisi tag ini dengan meneruskan objek konteks, seperti Peta atau Objek lainnya .

3.1. Menggunakan ini

Untuk mengirimkan satu nilai String ke template kita, kita bisa menggunakan Object sebagai konteksnya. Kita juga harus menggunakan ag {{ this}} di template kita.

Kemudian Handlebars memanggil metode toString pada objek konteks dan mengganti tag dengan hasil:

@Test public void whenThereIsNoTemplateFile_ThenCompilesInline() throws IOException { Handlebars handlebars = new Handlebars(); Template template = handlebars.compileInline("Hi {{this}}!"); String templateString = template.apply("Baeldung"); assertThat(templateString).isEqualTo("Hi Baeldung!"); }

Dalam contoh di atas, pertama-tama kita membuat instance Handlebars, titik masuk API kita.

Kemudian, kami memberikan contoh itu template kami. Di sini, kita hanya meneruskan template sebaris, tetapi kita akan melihat beberapa saat lagi cara yang lebih efektif.

Akhirnya, kami memberikan template terkompilasi konteks kami. {{this}} pada akhirnya hanya akan memanggil toString, itulah sebabnya kita melihat “Hai Baeldung!” .

3.2. Meneruskan Peta sebagai Objek Konteks

Kami baru saja melihat cara mengirim String untuk konteks kami, sekarang mari kita coba Peta :

@Test public void whenParameterMapIsSupplied_thenDisplays() throws IOException { Handlebars handlebars = new Handlebars(); Template template = handlebars.compileInline("Hi {{name}}!"); Map parameterMap = new HashMap(); parameterMap.put("name", "Baeldung"); String templateString = template.apply(parameterMap); assertThat(templateString).isEqualTo("Hi Baeldung!"); }

Mirip dengan contoh sebelumnya, kami menyusun template kami dan kemudian meneruskan objek konteks, tetapi kali ini sebagai Peta .

Selain itu, perhatikan bahwa kami menggunakan {{name}} daripada {{this}} . Artinya peta kita harus berisi key, name .

3.3. Meneruskan Objek Kustom sebagai Objek Konteks

Kami juga dapat mengirimkan objek khusus ke template kami:

public class Person { private String name; private boolean busy; private Address address = new Address(); private List friends = new ArrayList(); public static class Address { private String street; } }

Menggunakan kelas Person , kita akan mendapatkan hasil yang sama seperti contoh sebelumnya:

@Test public void whenParameterObjectIsSupplied_ThenDisplays() throws IOException { Handlebars handlebars = new Handlebars(); Template template = handlebars.compileInline("Hi {{name}}!"); Person person = new Person(); person.setName("Baeldung"); String templateString = template.apply(person); assertThat(templateString).isEqualTo("Hi Baeldung!"); }

{{name}} di template kita akan menelusuri objek Person kita dan mendapatkan nilai bidang nama .

4. Pemuat Template

Sejauh ini, kami telah menggunakan templat yang ditentukan di dalam kode. Namun, itu bukan satu-satunya pilihan. Kami juga dapat membaca template dari file teks.

Handlebars.java menyediakan dukungan khusus untuk membaca template dari classpath, filesystem atau konteks servlet. Secara default, Handlebars memindai classpath untuk memuat template yang diberikan:

@Test public void whenNoLoaderIsGiven_ThenSearchesClasspath() throws IOException { Handlebars handlebars = new Handlebars(); Template template = handlebars.compile("greeting"); Person person = getPerson("Baeldung"); String templateString = template.apply(person); assertThat(templateString).isEqualTo("Hi Baeldung!"); }

Jadi, karena kita memanggil compile dan bukan compileInline, ini adalah petunjuk bagi Handlebars untuk mencari /greeting.hbs di classpath.

Namun, kami juga dapat mengonfigurasi properti ini dengan ClassPathTemplateLoader :

@Test public void whenClasspathTemplateLoaderIsGiven_ThenSearchesClasspathWithPrefixSuffix() throws IOException { TemplateLoader loader = new ClassPathTemplateLoader("/handlebars", ".html"); Handlebars handlebars = new Handlebars(loader); Template template = handlebars.compile("greeting"); // ... same as before }

Dalam kasus ini, kami memberi tahu Handlebars untuk mencari /handlebars/greeting.html di classpath .

Akhirnya, kita dapat menghubungkan beberapa contoh TemplateLoader :

@Test public void whenMultipleLoadersAreGiven_ThenSearchesSequentially() throws IOException { TemplateLoader firstLoader = new ClassPathTemplateLoader("/handlebars", ".html"); TemplateLoader secondLoader = new ClassPathTemplateLoader("/templates", ".html"); Handlebars handlebars = new Handlebars().with(firstLoader, secondLoader); // ... same as before }

Jadi, di sini, kita punya dua pemuat, dan itu berarti Handlebars akan mencari dua direktori untuk template ucapan .

5. Pembantu Bawaan

Pembantu bawaan memberi kami fungsionalitas tambahan saat menulis templat kami.

5.1. dengan Helper

The with helper mengubah konteks saat ini :

{{#with address}} 

I live in {{street}}

{{/with}}

Dalam contoh template kami, tag {{#with address}} memulai bagian dan tag {{/ with}} mengakhirinya .

Pada intinya, kita pengeboran sedang ke objek konteks saat ini - mari katakanlah p erson - dan pengaturan alamat sebagai konteks lokal untuk dengan bagian . Setelah itu, setiap referensi bidang di bagian ini akan ditambahkan oleh person.address .

Jadi, tag {{street}} akan menyimpan nilai person.address.street :

@Test public void whenUsedWith_ThenContextChanges() throws IOException { Handlebars handlebars = new Handlebars(templateLoader); Template template = handlebars.compile("with"); Person person = getPerson("Baeldung"); person.getAddress().setStreet("World"); String templateString = template.apply(person); assertThat(templateString).contains("

I live in World

"); }

Kami sedang menyusun template kami dan menetapkan instance Person sebagai objek konteks. Perhatikan bahwa kelas Person memiliki bidang Alamat . Ini adalah field yang kita suplai ke with helper.

Though we went one level into our context object, it is perfectly fine to go deeper if the context object has several nested levels.

5.2. each Helper

The each helper iterates over a collection:

{{#each friends}} {{name}} is my friend. {{/each}}

As a result of starting and closing the iteration section with {{#each friends}} and {{/each}} tags, Handlebars will iterate over the friends field of the context object.

@Test public void whenUsedEach_ThenIterates() throws IOException { Handlebars handlebars = new Handlebars(templateLoader); Template template = handlebars.compile("each"); Person person = getPerson("Baeldung"); Person friend1 = getPerson("Java"); Person friend2 = getPerson("Spring"); person.getFriends().add(friend1); person.getFriends().add(friend2); String templateString = template.apply(person); assertThat(templateString) .contains("Java is my friend.", "Spring is my friend."); }

In the example, we're assigning two Person instances to the friends field of the context object. So, Handlebars repeats the HTML part two times in the final output.

5.3. if Helper

Terakhir, yang jika helper memberikan render bersyarat .

{{#if busy}} 

{{name}} is busy.

{{else}}

{{name}} is not busy.

{{/if}}

Di templat kami, kami memberikan pesan berbeda sesuai dengan bidang sibuk .

@Test public void whenUsedIf_ThenPutsCondition() throws IOException { Handlebars handlebars = new Handlebars(templateLoader); Template template = handlebars.compile("if"); Person person = getPerson("Baeldung"); person.setBusy(true); String templateString = template.apply(person); assertThat(templateString).contains("

Baeldung is busy.

"); }

Setelah menyusun template, kami mengatur objek konteks. Karena bidang busy benar , hasil akhirnya menjadi

Baeldung sedang sibuk.

.

6. Pembantu Template Kustom

Kami juga dapat membuat pembantu khusus kami sendiri.

6.1. Pembantu

The Helper antarmuka memungkinkan kita untuk membuat pembantu Template.

Sebagai langkah pertama, kita harus menyediakan implementasi Helper :

new Helper() { @Override public Object apply(Person context, Options options) throws IOException { String busyString = context.isBusy() ? "busy" : "available"; return context.getName() + " - " + busyString; } }

As we can see, the Helper interface has only one method which accepts the context and options objects. For our purposes, we'll output the name and busy fields of Person.

After creating the helper, we must also register our custom helper with Handlebars:

@Test public void whenHelperIsCreated_ThenCanRegister() throws IOException { Handlebars handlebars = new Handlebars(templateLoader); handlebars.registerHelper("isBusy", new Helper() { @Override public Object apply(Person context, Options options) throws IOException { String busyString = context.isBusy() ? "busy" : "available"; return context.getName() + " - " + busyString; } }); // implementation details }

In our example, we're registering our helper under the name of isBusy using the Handlebars.registerHelper() method.

As the last step, we must define a tag in our template using the name of the helper:

{{#isBusy this}}{{/isBusy}}

Notice that each helper has a starting and ending tag.

6.2. Helper Methods

When we use the Helper interface, we can only create only one helper. In contrast, a helper source class enables us to define multiple template helpers.

Moreover, we don't need to implement any specific interface. We just write our helper methods in a class then HandleBars extracts helper definitions using reflection:

public class HelperSource { public String isBusy(Person context) { String busyString = context.isBusy() ? "busy" : "available"; return context.getName() + " - " + busyString; } // Other helper methods }

Since a helper source can contain multiple helper implementations, registration is different than the single helper registration:

@Test public void whenHelperSourceIsCreated_ThenCanRegister() throws IOException { Handlebars handlebars = new Handlebars(templateLoader); handlebars.registerHelpers(new HelperSource()); // Implementation details }

We're registering our helpers using the Handlebars.registerHelpers() method. Moreover, the name of the helper method becomes the name of the helper tag.

7. Template Reuse

The Handlebars library provides several ways to reuse our existing templates.

7.1. Template Inclusion

Template inclusion is one of the approaches for reusing templates. It favors the composition of the templates.

Hi {{name}}!

This is the content of the header template – header.html.

In order to use it in another template, we must refer to the header template.

{{>header}} 

This is the page {{name}}

We have the page template – page.html – which includes the header template using {{>header}}.

When Handlebars.java processes the template, the final output will also contain the contents of header:

@Test public void whenOtherTemplateIsReferenced_ThenCanReuse() throws IOException { Handlebars handlebars = new Handlebars(templateLoader); Template template = handlebars.compile("page"); Person person = new Person(); person.setName("Baeldung"); String templateString = template.apply(person); assertThat(templateString) .contains("

Hi Baeldung!

", "

This is the page Baeldung

"); }

7.2. Template Inheritance

Alternatively to composition, Handlebars provides the template inheritance.

We can achieve inheritance relationships using the {{#block}} and {{#partial}} tags:

  {{#block "intro"}} This is the intro {{/block}} {{#block "message"}} {{/block}}  

By doing so, the messagebase template has two blocks – intro and message.

To apply inheritance, we need to override these blocks in other templates using {{#partial}}:

{{#partial "message" }} Hi there! {{/partial}} {{> messagebase}}

This is the simplemessage template. Notice that we're including the messagebase template and also overriding the message block.

8. Summary

In this tutorial, we've looked at Handlebars.java to create and manage templates.

We started with the basic tag usage and then looked at the different options to load the Handlebars templates.

Kami juga menyelidiki pembantu template yang menyediakan banyak fungsi. Terakhir, kami melihat berbagai cara untuk menggunakan kembali template kami.

Terakhir, periksa kode sumber untuk semua contoh di GitHub.