今回は、Ext.XTemplateを取り上げます。

Ext.XTemplateはテンプレート機能を提供してくれます。同じようなパターンの文字列を何度も作成する場合に便利です。

多くのjavascriptフレームワークでも実装されており、HTMLタグ文字列を作成するのに使われることが多くです。

ExtJSでも同様に、多くのコンポーネントクラスの実装で使われており、使えるようになるとExtJSでの開発が非常に楽になります。

まずは使ってみる

これは挨拶の文字列を出力する簡単なサンプルです。

var tpl = new Ext.XTemplate({name}さん、こんにちは);

var str = tpl.apply({
    name: 山田太郎
});

console.log(str);

基本的な使い方は↓です。

1. Ext.XTemplateのコンストラクタにテンプレート用の文字列を渡す。
2. applyメソッドに埋め込みデータを渡す

applyメソッド以外にもデータを渡すためのメソッドは存在しますが、単純な文字列を返す場合はapplyメソッドを使います。

条件分岐

データの内容によって、テンプレート文字列で条件分岐することができます。

テンプレート文字列でを使うと、if内がtrueの場合、囲った部分が出力されます。

var tpl = new Ext.XTemplate(
    {name}<tpl if="kana">({kana})</tpl>さん、こんにちは
);

var str = tpl.apply({
    name: 山田太郎,
    kana: やまだたろう
});

console.log(str);

上記のサンプルでは、埋め込みデータにkanaがあれば、ふりがなを括弧付きで出力します。

applyメソッドに渡すオブジェクトリテラルからkanaを消してみると、括弧部分も表示されなくなります。

大小関係を条件にする場合は、下記のようになります。(tplタグ内に書くので括弧が使えないのは良いとして、leやgeが存在しないのが謎です)

一般的なオペレータ テンプレート文字列でのオペレータ
> &gt;
>= &gt;=
< &lt;
<= &lt;=
== ==
var tpl = new Ext.XTemplate(
    商品名: {name}
,
    サイズ: ,
    <tpl if="weight &gt;= 1000">,
        ,
    <tpl elseif="weight &gt;= 500">,
        ,
    <tpl else>,
        ,
    </tpl>
);

var str = tpl.apply({
    name: りんご,
    weight: 500
});

console.log(str);

これを実行するとサイズは「中」と出力されます。

ついでに使いましたが、elseifやelseで複数条件を指定することもできます。

繰り返し

を使って、配列なども繰り返し処理できます。

var tpl = new Ext.XTemplate(
    <tpl for="items">,
        商品名: {name}, 価格: {price}円
,
    </tpl>
);

var str = tpl.apply({
    items: [
        {
            name: 帽子,
            price: 1800
        },
        {
            name: Tシャツ,
            price: 1000
        },
        {
            name: バッグ,
            price: 5000
        }
    ]
});

console.log(str);

forには、繰り返し処理するデータのプロパティ名を指定します。

すると、内では、繰り返し処理中の1件分が処理のスコープとなり、サンプルのように直接{name}や{price}が指定できます。

親のデータにアクセスしないといけない場合は、parentを通して取得します。

var tpl = new Ext.XTemplate(
    <tpl for="items">,
        商品名: {name}, 価格: {price}円, 税率: {parent.tax}
,
    </tpl>
);

var str = tpl.apply({
    tax: 0.08,
    items: [
        {
            name: 帽子,
            price: 1800
        },
        {
            name: Tシャツ,
            price: 1000
        },
        {
            name: バッグ,
            price: 5000
        }
    ]
});

console.log(str);

ループのインデックス番号などもアクセスできます。

インデックス番号の場合は「xindex」です。他にもあるのでドキュメントを参照してみてください(http://docs.sencha.com/extjs/6.2.1/modern/Ext.XTemplate.html)。

var tpl = new Ext.XTemplate(
    <tpl for="text">,
        {% if (xindex % 2 === 0) continue; %},
        {.}
,
        {% if (xindex > 8) break; %},
    </tpl>
);

var str = tpl.apply({
    text: [
        item1,
        item2,
        item3,
        item4,
        item5,
        item6,
        item7,
        item8,
        item9,
        item10
    ]
});

console.log(str);

{% … %}は、出力を伴わないような制御処理で使えます。出力まで伴う場合には、{[…]}を使うことができます(次のセクション)。

計算処理やメソッド定義

テンプレート内で同じような判定や計算があれば、メソッドにまとめることができます。

var tpl = new Ext.XTemplate(
    <tpl for="items">,
        商品名: {name}, 価格: {price}円,
        <tpl if="!this.isTaxFree(values)">,
            , 消費税: {[this.calcTax(values.price, parent.taxRate)]}円
,
        </tpl>,
    </tpl>,
    {
        isTaxFree: function (values) {
            return values.taxFree;
        },
        calcTax: function (price, taxRate) {
            return Math.floor(price * taxRate);
        }
    }
);

var str = tpl.apply({
    taxRate: 0.08,
    items: [
        {
            name: 帽子,
            price: 1800,
            taxFree: false
        },
        {
            name: Tシャツ,
            price: 1000,
            taxFree: false
        },
        {
            name: バッグ,
            price: 5000,
            taxFree: true
        }
    ]
});

console.log(str);

Ext.XTemplateの最後にオブジェクトリテラルでメソッドを定義することができます。

出力させる場合は{[…]}に記述します。定義したメソッドはExt.XTemplateのメンバーメソッドになるので、thisキーワードから実行します。

埋め込みデータはvaluesに格納されているので、そこを経由してアクセスできます。

また、ifでもメソッドを使えるので、条件が複雑な場合はメソッドを定義すると便利です。

コンポーネントで使ってみる

最後にコンポーネントで使ってみましょう。

Ext.define(Sample.view.main.Panel, {
    extend: Ext.panel.Panel,
    xtype: main_panel,

    bodyPadding: 20,

    tpl: [
        <header>,
            <h1>{title}</h1>,
        </header>,
        <section>,
            <p>{content}</p>,
        </section>
    ],

    data: {
        title: Ext.XTemplateの紹介,
        content: Ext.XTemplateを紹介しています。<br>便利な機能なのでぜひ使ってみてください。
    }
});

f:id:sham-memo:20170326142550p:plain

上記の場合は、tplコンフィグがテンプレート文字列、dataコンフィグがそれに埋め込むデータとなります。

dataが設定されると、内部でExt.XTemplateが使われてDOMが生成・更新されるようになっているのです。