ハンドルバーを使用したテンプレート

1. 概要

このチュートリアルでは、テンプレート管理を簡単にするためにhttps://jknack.github.io/handlebars.java/[Handlebars.java]ライブラリを調べます。

2. Mavenの依存関係

_https://search.maven.org/search?q = g:com.github.jknack%2Ba:handlebars [handlebars] _依存関係の追加から始めましょう。
<dependency>
    <groupId>com.github.jknack</groupId>
    <artifactId>handlebars</artifactId>
    <version>4.1.2</version>
</dependency>

3. シンプルなテンプレート

Handlebarsテンプレートには、あらゆる種類のテキストファイルを使用できます。 *これは、* _ * \ {\ {name}}および\ {\ {#each people}}のようなタグで構成されています。* _
次に、_Map_やその他の_Object._などのコンテキストオブジェクトを渡すことで、これらのタグを埋めます。

3.1. _this_を使用する

*テンプレートに単一の_String_値を渡すには、任意の_Object_をコンテキストとして使用できます。*テンプレートで\ {\ {__ this}} t__agも使用する必要があります。
次に、Handlebarsはコンテキストオブジェクトで_toString_メソッドを呼び出し、タグを結果に置き換えます。
@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!");
}
上記の例では、最初に__Handlebars、__our APIエントリポイントのインスタンスを作成します。
次に、そのインスタンスにテンプレートを与えます。 ここでは、*テンプレートをインラインで渡します*が、より強力な方法がすぐにわかります。
最後に、コンパイルされたテンプレートにコンテキストを与えます。 _ \ {\ {this}} _は_toStringを呼び出すことになります_。

3.2. _Map_をコンテキストオブジェクトとして渡す

コンテキストに_String_を送信する方法を見ましたが、今度は_Map_を試してみましょう。
@Test
public void whenParameterMapIsSupplied_thenDisplays() throws IOException {
    Handlebars handlebars = new Handlebars();
    Template template = handlebars.compileInline("Hi {{name}}!");
    Map<String, String> parameterMap = new HashMap<>();
    parameterMap.put("name", "Baeldung");

    String templateString = template.apply(parameterMap);

    assertThat(templateString).isEqualTo("Hi Baeldung!");
}
前の例と同様に、テンプレートをコンパイルしてからコンテキストオブジェクトを渡しますが、今回は_Map_として渡します。
また、_ \ {\ {this}} _の代わりに_ \ {\ {name}} _を使用していることに注意してください。 **これは、マップにキー_name _ ** __が含まれている必要があることを意味します。 __

3.3. カスタムオブジェクトをコンテキストオブジェクトとして渡す

*カスタムオブジェクトをテンプレートに渡すこともできます:*
public class Person {
    private String name;
    private boolean busy;
    private Address address = new Address();
    private List<Person> friends = new ArrayList<>();

    public static class Address {
        private String street;
    }
}
_Person_クラスを使用すると、前の例と同じ結果が得られます。
@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}} _は_Person_オブジェクトにドリルし、__ name __field_の値を取得します。 _

4. テンプレートローダー

これまで、コード内で定義されたテンプレートを使用しました。 ただし、これが唯一のオプションではありません。 *テキストファイルからテンプレートを読み取ることもできます。*
Handlebars.javaは、クラスパス、ファイルシステム、またはサーブレットコンテキストからテンプレートを読み取るための特別なサポートを提供します。 *デフォルトでは、Handlebarsはクラスパスをスキャンして指定されたテンプレートをロードします*
@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!");
}
*したがって、_compileInline、_ *の代わりに_compile_を呼び出したため、これはクラスパスで_ / greeting.hbs_を探すためのHandlebarsへのヒントです。
ただし、_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
}
この場合、クラスパスで_ / handlebars / greeting.html_を検索するように* Handlebarsに指示しています。
最後に、複数の_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
}
そのため、ここには2つのローダーがあります。つまり、Handlebarは2つのディレクトリで_greeting_テンプレートを検索します。

5. 組み込みヘルパー

組み込みヘルパーは、テンプレートを作成するときに追加機能を提供します。

5.1. _with_ヘルパー

  • _with_ヘルパーは現在のコンテキストを変更します*:

{{#with address}}
<h4>I live in {{street}}</h4>
{{/with}}
サンプルテンプレートでは、_ \ {\ {#with address}} _タグでセクションを開始し、_ \ {\ {/ with}} _タグで終了します__.__
**本質的に、現在のコンテキストオブジェクトにドリルします。たとえば、p__erson__ –と_with_セクションのローカルコンテキストとして_address_を設定します** __.__その後、このセクションのすべてのフィールド参照は_person.address_で先頭に追加されます。
したがって、_ \ {\ {street}} _タグには_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).isEqualTo("\n<h4>I live in World</h4>\n");
}
テンプレートをコンパイルし、_Person_インスタンスをコンテキストオブジェクトとして割り当てています。 _Person_クラスには_Address_フィールドがあることに注意してください。 これは、_with_ヘルパーに提供するフィールドです。
*コンテキストオブジェクトに1レベル移動しましたが、コンテキストオブジェクトに複数のネストレベルがある場合は、さらに深くしても問題ありません。*

5.2. _each_ヘルパー

  • _each_ヘルパーはコレクションを反復処理します*:

{{#each friends}}
<span>{{name}} is my friend.</span>
{{/each}}
_ \ {\ {#each friends}} _および_ \ {\ {/ each}} _タグで反復セクションを開始および終了した結果、ハンドルバーはコンテキストオブジェクトの_friends_フィールドを反復処理します。
@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).isEqualTo("\n<span>Java is my friend.</span>\n"
                                           + "\n<span>Spring is my friend.</span>\n");
}
この例では、2つの_Person_インスタンスをコンテキストオブジェクトの_friends_フィールドに割り当てています。 したがって、Handlebarsは最終出力でHTML部分を2回繰り返します。

5.3. _if_ヘルパー

最後に、* if_ヘルパーは条件付きレンダリング*を提供します。
{{#if busy}}
<h4>{{name}} is busy.</h4>
{{else}}
<h4>{{name}} is not busy.</h4>
{{/if}}
テンプレートでは、_busy_フィールドに従って異なるメッセージを提供しています。
@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).isEqualTo("\n<h4>Baeldung is busy.</h4>\n");
}
テンプレートをコンパイルした後、コンテキストオブジェクトを設定しています。 * _busy_フィールドが_true_であるため、最終出力は_ <h4> Baeldung is busy。</ h4> _ *になります。

6. カスタムテンプレートヘルパー

独自のカスタムヘルパーを作成することもできます。

6.1. ヘルパー

  • _Helper_インターフェイスを使用すると、テンプレートヘルパーを作成できます。*

    最初のステップとして、_Helper_の実装を提供する必要があります。
new Helper<Person>() {
    @Override
    public Object apply(Person context, Options options) throws IOException {
        String busyString = context.isBusy() ? "busy" : "available";
        return context.getName() + " - " + busyString;
    }
}
ご覧のとおり、_Helper_インターフェイスには、_context_および_options_オブジェクトを受け入れるメソッドが1つしかありません。 この目的のために、_Person_の_name_および_busy_フィールドを出力します。
*ヘルパーを作成した後、カスタムヘルパーをHandlebars *に登録する必要もあります。
@Test
public void whenHelperIsCreated_ThenCanRegister() throws IOException {
    Handlebars handlebars = new Handlebars(templateLoader);
    handlebars.registerHelper("isBusy", new Helper<Person>() {
        @Override
        public Object apply(Person context, Options options) throws IOException {
            String busyString = context.isBusy() ? "busy" : "available";
            return context.getName() + " - " + busyString;
        }
    });

    // implementation details
}
この例では、_Handlebars.registerHelper()_メソッドを使用して、_isBusy_という名前でヘルパーを登録しています。
*最後のステップとして、ヘルパーの名前を使用してテンプレートにタグを定義する必要があります*:
{{#isBusy this}}{{/isBusy}}
各ヘルパーには開始タグと終了タグがあることに注意してください。

6.2. ヘルパーメソッド

  • _Helper_インターフェイスを使用する場合、作成できるヘルパーは1つだけです*。 対照的に、ヘルパーソースクラスを使用すると、複数のテンプレートヘルパーを定義できます。

    さらに、特定のインターフェイスを実装する必要はありません。 ヘルパーメソッドをクラスに記述するだけで、HandleBarsはリフレクションを使用してヘルパー定義を抽出します。
public class HelperSource {

    public String isBusy(Person context) {
        String busyString = context.isBusy() ? "busy" : "available";
        return context.getName() + " - " + busyString;
    }

    // Other helper methods
}
ヘルパーソースには複数のヘルパー実装を含めることができるため、登録は単一のヘルパー登録とは異なります。
@Test
public void whenHelperSourceIsCreated_ThenCanRegister() throws IOException {
    Handlebars handlebars = new Handlebars(templateLoader);
    handlebars.registerHelpers(new HelperSource());

    // Implementation details
}
_Handlebars.registerHelpers()_メソッドを使用してヘルパーを登録しています。 さらに、*ヘルパーメソッドの名前はヘルパータグの名前*になります。

7. テンプレートの再利用

Handlebarsライブラリは、既存のテンプレートを再利用するいくつかの方法を提供します。

7.1. テンプレートの包含

*テンプレートの包含は、テンプレートを再利用するためのアプローチの1つです。 テンプレートの構成を優先します*。
<h4>Hi {{name}}!</h4>
これは、_header_テンプレートのコンテンツです-_header.html._
別のテンプレートで使用するには、_header_テンプレートを参照する必要があります。
{{>header}}
<p>This is the page {{name}}</p>
_ \ {\ {> header}}を使用して_header_テンプレートを含む_page_テンプレート_– page.html –_があります。
Handlebars.javaがテンプレートを処理すると、最終出力には_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).isEqualTo("<h4>Hi Baeldung!</h4>\n<p>This is the page Baeldung</p>");
}

7.2. テンプレートの継承

コンポジションの代わりに、* Handlebarsはテンプレートの継承を提供します*。
_ \ {\ {#block}} _および_ \ {\ {#partial}} _タグを使用して継承関係を実現できます。
<html>
<body>
{{#block "intro"}}
  This is the intro
{{/block}}
{{#block "message"}}
{{/block}}
</body>
</html>
そうすることで、_messagebase_テンプレートには2つのブロックがあります-_intro_と_message_。
継承を適用​​するには、_ \ {\ {#partial}} _を使用して他のテンプレートでこれらの_blocks_をオーバーライドする必要があります。
{{#partial "message" }}
  Hi there!
{{/partial}}
{{> messagebase}}
これが_simplemessage_テンプレートです。 _messagebase_テンプレートを含め、_message_ブロックをオーバーライドしていることに注意してください。

8. 概要

このチュートリアルでは、テンプレートを作成および管理するためのHandlebars.javaを確認しました。
基本的なタグの使用から始めて、Handlebarsテンプレートをロードするためのさまざまなオプションを調べました。
また、多くの機能を提供するテンプレートヘルパーについても調査しました。 最後に、テンプレートを再利用するさまざまな方法を検討しました。
最後に、すべての例のソースコードhttps://github.com/eugenp/tutorials/tree/master/libraries-2[GitHubで]を確認してください。