この記事はMTAppjQuery Advent Calendar 2018の1日目の記事です。
祝)今年から始まったMTAppjQueryのAdvent Calendar一発目の記事を書きたいと思います。
初日の内容は、MTAppjQuery 2から実装されたmultiFieldの表示側の取り出し方について書きたいと思います。
user.jsで設定したブロックをどのように取り出すのか参考になればと思います。
MTAppjQuery 2から実装されたmultiFieldでは、好きなレイアウトモジュールのフィールド(グループで組み合わせたり)を任意で設定することができます。※user.jsに好きなフィールドタイプを定義していく形になります。
入力された値はJSONとして保存されるので、MTタグと組み合わせて出力させます。
入力された値は、JSONとして保存されます。
保存された値をテンプレートに出力させるためにはmt:Loopなどループ系のタグを使い取り出します。
mt:Loop
の使い方については、以下のドキュメントを参照してみてください。
また、v2.3.0 mt:Foreach
、 mt:NestVar
が実装されました。
今回は単純に mt:Loop
を回した場合と mt:Foreach
、 mt:NestVar
を使った場合の比較したいと思います。
また、サンプルコードでは見た目を整えるために UIkit というCSSフレームワークを使っています。
multiFieldの設定したブロックフィールド
まずは、user.jsに multiField
を設定します。
投稿系で考えられる必要最低限のブロックフィールドを用意しておきました。
設定したフィールド
- 見出し01(h1)
- 見出し02(h2)
- 見出し03(h3)
- テキスト(txt)
- 複数テキスト(textarea)
- 画像単体アップロード(img)
- 表組み(table)
- リスト(ul)
- 画像単体アップロード + テキスト(img + text)
user.js Code
user.jsは以下のように設定しています。
設定したフィールドは mtapp.multiField
の部分のように記述します。
multiFieldの設定では、id
は必須になるため .nav-tabs
の部分でフィールドをeachで回して特定のフィールド名の id
を取得して関数を実行するようにしています。
この処理を加えておくことで本番・開発環境でのidの差異をなくすために記述しています。
"use strict";
var DEMO_MT7 = {};
var demo_mt7;
DEMO_MT7 = function () {
this.init();
};
(function ($, window, document, undefined) {
/*
* ==================================================
* NOTE: config
* ==================================================
*/
DEMO_MT7.prototype = {
/*
* 初期設定
*/
init: function () {
var self = this;
$(".nav-tabs").each(function () {
var id = $(this).prop("id");
var number = id.match(/(\d+)/g);
var label_text = $(this).find("label").text().trim();
if (label_text === "マルチフィールド") {
multiFieldFunc(number);
}
});
function multiFieldFunc(id) {
mtapp.multiField({
debug: false,
id: id,
label: "マルチフィールド",
fieldGroups: [
[
{ type: "h1", label: "見出し01" },
{ type: "h2", label: "見出し02" },
{ type: "h3", label: "見出し03" },
],
[
{ type: "text", label: "1行テキスト" },
{ type: "textarea", label: "複数行テキスト", rows: 8 },
{ type: "image", label: "画像単体アップロード" },
],
[
{
type: "table",
label: "表組み",
options: [
{ type: "text", label: "見出し" },
{ type: "textarea", label: "テキスト" },
],
},
{
type: "table",
label: "リスト",
options: [
{ type: "url", label: "URL" },
{ type: "text", label: "テキスト" },
],
},
],
[
{
type: "multi-column-content",
label: "画像単体アップロード + テキスト",
options: [
[{ type: "text", label: "キャプション" }],
[{ type: "image", label: "画像" }],
],
},
],
],
});
}
},
};
})(jQuery, window, document);
demo_mt7 = new DEMO_MT7();
例)MovableType標準タグのmt:Loopで出力
コンテンツフィールドをマルチフィールドにしたフィールドを json_decode
して変数に格納します。
<mt:SetVarBlock name="multifield"
><mt:ContentField content_field="マルチフィールド"
><mt:ContentFieldValue /></mt:ContentField
></mt:SetVarBlock>
<mt:Var name="multifield" convert_breaks="0" json_decode="1" setvar="json" />
<mt:Var name="json" key="items" setvar="items" />
json_decode
で格納した変数を mt:Loop
で取り出します。
どのようなJSONが確認するには、マルチフィールドにある「保存データを表示」で参照することが出来ます。
mt:Loop
でマルチフィールドの取り出しは以下のようになります。
深いJSONの値を取得するために都度 mt:Loop
で潜る必要があります。
とくに複雑な書き方になるのは連続するフィールド(テーブル)や様々なフィールドをグループ化するフィールド(マルチカラムコンテンツ)ループを入れ子にしなければならないフィールドはテーブルやマルチカラムコンテンツになります。
mt:Loop
で取り出す場合は、かなり表示側のテンプレが長くなってしまう問題があります。
今回のサンプルでは紹介しませんが、 SetVarTemplate
を駆使してコンポーネント化するような設計が良いかと思います。
- mt:Loopでitemsを回す
- mt:Ifでtypeやlabelの条件を設定
- マッチした値を出力
- 深いJSONの値はさらにmt:Loopで回す
<mt:Var name="json" key="items" setvar="items" />
<mt:SetVar name="items_index" value="0" />
<mt:Loop name="items">
<mt:Var name="items" index="$items_index" setvar="item" />
<mt:Ignore>見出しレベル</mt:Ignore>
<mt:If name="item" key="type" eq="h1">
<h1 class="uk-heading-bullet"><mt:Var name="item" key="data" /></h1>
</mt:If>
<mt:If name="item" key="type" eq="h2">
<h2 class="uk-heading-line"><mt:Var name="item" key="data" /></h2>
</mt:If>
<mt:If name="item" key="type" eq="h3">
<h3 class="uk-heading-divider"><mt:Var name="item" key="data" /></h3>
</mt:If>
<mt:Ignore>テキストレベル</mt:Ignore>
<mt:If name="item" key="type" eq="text">
<p><mt:Var name="item" key="data" /></p>
</mt:If>
<mt:If name="item" key="type" eq="textarea">
<p><mt:Var name="item" key="data" remove_html="1" convert_breaks="0" nl2br="1" /></p>
</mt:If>
<mt:Ignore>画像アップロード</mt:Ignore>
<mt:If name="item" key="type" eq="image">
<div class="uk-margin-auto uk-margin-auto-vertical uk-width-1-2@s uk-card uk-card-default uk-card-body">
<img src="<mt:Var name="item" key="url" />">
</div>
</mt:If>
<mt:Ignore>テーブル</mt:Ignore>
<mt:If name="item" key="type" eq="table">
<mt:Var name="item" key="data" setvar="_data" />
<mt:Ignore>表組み</mt:Ignore>
<mt:If name="item" key="label" eq="表組み">
<mt:SetVar name="items_index2" value="0" />
<mt:Loop name="_data">
<mt:Var name="_data" index="$items_index2" setvar="__data" />
<mt:SetVar name="items_index3" value="0" />
<mt:If name="__first__"><table class="uk-table uk-table-hover uk-table-divider"></mt:If>
<mt:Loop name="__data">
<mt:Var name="__data" index="$items_index3" setvar="___data" />
<mt:If name="___data" key="label" eq="見出し"><mt:Var name="___data" key="data" setvar="__title" /></mt:If>
<mt:If name="___data" key="label" eq="テキスト"><mt:Var name="___data" key="data" setvar="__text" /></mt:If>
<mt:SetVar name="items_index3" op="++" />
</mt:Loop>
<tr>
<mt:If name="__title"><th><mt:Var name="__title" /></th></mt:If>
<mt:If name="__text"><td><mt:Var name="__text" /></td></mt:If>
</tr>
<mt:If name="__last__"></table></mt:If>
<mt:SetVar name="items_index2" op="++" />
</mt:Loop>
</mt:If>
<mt:Ignore>リスト</mt:Ignore>
<mt:If name="item" key="label" eq="リスト">
<mt:SetVar name="items_index2" value="0" />
<mt:Loop name="_data">
<mt:Var name="_data" index="$items_index2" setvar="__data" />
<mt:SetVar name="items_index3" value="0" />
<mt:If name="__first__"><ul class="uk-list uk-list-bullet"></mt:If>
<mt:Loop name="__data">
<mt:Var name="__data" index="$items_index3" setvar="___data" />
<mt:If name="___data" key="label" eq="テキスト"><mt:Var name="___data" key="data" setvar="__text" /></mt:If>
<mt:If name="___data" key="label" eq="URL"><mt:Var name="___data" key="data" setvar="__url" /></mt:If>
<mt:SetVar name="items_index3" op="++" />
</mt:Loop>
<mt:If name="__text"><li><mt:If name="__url"><a href="<mt:Var name='__url' />" target="_blank" target="_blank"></mt:If><mt:Var name="__text" /></li><mt:If name="__url"></a></mt:If></mt:If>
<mt:If name="__last__"></ul></mt:If>
<mt:SetVar name="items_index2" op="++" />
</mt:Loop>
</mt:If>
</mt:If>
<mt:Ignore>マルチカラムコンテンツ</mt:Ignore>
<mt:If name="item" key="type" eq="multi-column-content">
<mt:Var name="item" key="data" setvar="_data" />
<mt:Ignore>画像単体アップロード + テキスト</mt:Ignore>
<mt:If name="item" key="label" eq="画像単体アップロード + テキスト">
<mt:SetVar name="items_index2" value="0" />
<mt:Loop name="_data">
<mt:Var name="_data" index="$items_index2" setvar="__data" />
<mt:SetVar name="items_index3" value="0" />
<mt:Loop name="__data">
<mt:Var name="__data" index="$items_index3" setvar="___data" />
<mt:If name="___data" key="label" eq="画像"><mt:Var name="___data" key="url" setvar="img_url" /></mt:If>
<mt:If name="___data" key="label" eq="キャプション"><mt:Var name="___data" key="data" setvar="img_text" /></mt:If>
<mt:SetVar name="items_index3" op="++" />
</mt:Loop>
<mt:SetVar name="items_index2" op="++" />
</mt:Loop>
<mt:If name="img_url">
<div class="uk-flex-middle" uk-grid>
<div class="uk-width-2-3@m">
<p><mt:Var name="img_text" /></p>
</div>
<div class="uk-width-1-3@m uk-flex-first">
<img src="<mt:Var name='img_url' />">
</div>
</div>
</mt:If>
</mt:If>
</mt:If>
<mt:SetVar name="items_index" op="++" />
</mt:Loop>
例)v2.3.0から実装されたmt:Foreach、mt:NestVarタグで出力
v2.3.0から実装されたタグ mt:Foreach
、 mt:NestVar
を使うことで単純にインクリメントせずにループが可能になり且つ深いJSONを取り出すのをループを繰り返しせずにドットで取り出すことが可能になりました。
mt:Loop
と同じようにように設定した取り出し方の書いた例になります。
連続したフィールド(テーブル系)やマルチカラムコンテンツの値は mt:Loop
の取り出し方に比べるとわかりやすくなったと思います。
- mt:Foreachでmt:Loopのようなインクリメントせずにループが可能
- mt:NestVarでmt:Loopのような入れ子せずにドットで取得が可能
複雑なことをするとテンプレで行うロジックの見通しが悪くなり、デバッグや改修し辛いコードになると思います。
mt:Foreach
、 mt:NestVar
はテンプレ実装側としては嬉しいタグになります。(マルチフィールド以外でも利用できますし)
<mt:Foreach name="items" as="item">
<mt:Ignore>見出しレベル</mt:Ignore>
<mt:If name="item" key="type" eq="h1">
<h1 class="uk-heading-bullet"><mt:Var name="item" key="data" /></h1>
</mt:If>
<mt:If name="item" key="type" eq="h2">
<h2 class="uk-heading-line"><mt:Var name="item" key="data" /></h2>
</mt:If>
<mt:If name="item" key="type" eq="h3">
<h3 class="uk-heading-divider"><mt:Var name="item" key="data" /></h3>
</mt:If>
<mt:Ignore>テキストレベル</mt:Ignore>
<mt:If name="item" key="type" eq="text">
<p class="uk-text-small"><mt:Var name="item" key="data" /></p>
</mt:If>
<mt:If name="item" key="type" eq="textarea">
<p class="uk-text-small"><mt:Var name="item" key="data" remove_html="1" convert_breaks="0" nl2br="1" /></p>
</mt:If>
<mt:Ignore>画像アップロード</mt:Ignore>
<mt:If name="item" key="type" eq="image">
<div class="uk-margin-auto uk-margin-auto-vertical uk-width-1-2@s uk-card uk-card-default uk-card-body">
<img src="<mt:Var name="item" key="url" />">
</div>
</mt:If>
<mt:Ignore>テーブル</mt:Ignore>
<mt:If name="item" key="type" eq="table">
<mt:Ignore>表組み</mt:Ignore>
<mt:If name="item" key="label" eq="表組み">
<mt:Foreach name="item.data" as="_data">
<mt:If name="__first__"><table class="uk-table uk-table-hover uk-table-divider"></mt:If>
<tr>
<th><mt:NestVar name="_data.0.data" /></th>
<td><mt:NestVar name="_data.1.data" /></td>
</tr>
<mt:If name="__last__"></table></mt:If>
</mt:Foreach>
</mt:If>
<mt:Ignore>リスト</mt:Ignore>
<mt:If name="item" key="label" eq="リスト">
<mt:Foreach name="item.data" as="_data">
<mt:If name="__first__"><ul class="uk-list uk-list-bullet"></mt:If>
<li><a href="<mt:NestVar name='_data.0.data' />"><mt:NestVar name="_data.1.data" /></a></li>
<mt:If name="__last__"></ul></mt:If>
</mt:Foreach>
</mt:If>
</mt:If>
<mt:Ignore>マルチカラムコンテンツ</mt:Ignore>
<mt:If name="item" key="type" eq="multi-column-content">
<mt:Ignore>画像単体アップロード + テキスト</mt:Ignore>
<mt:If name="item" key="label" eq="画像単体アップロード + テキスト">
<mt:Foreach name="item.data" as="_data">
<mt:Ignore>テキストデータの初期化</mt:Ignore>
<mt:SetVar name="_text" />
<mt:If name="__first__">
<div class="uk-flex-middle" uk-grid>
</mt:If>
<mt:NestVar name="_data.0.type" setvar="_type" />
<mt:If name="_type" eq="text">
<mt:NestVar name="_data.0.data" setvar="_text" />
</mt:If>
<mt:NestVar name='_data.0.url' setvar="_url" />
<mt:If name="_text">
<div class="uk-width-2-3@m">
<p><mt:Var name="_text" /></p>
</div>
</mt:If>
<mt:If name="_url">
<div class="uk-width-1-3@m uk-flex-first">
<img src="<mt:NestVar name='_data.0.url' />">
</div>
</mt:If>
<mt:If name="__last__">
</div>
</mt:If>
</mt:Foreach>
</mt:If>
</mt:If>
</mt:Foreach>
最終コードはこちら
最終的に出来たコードをGistに書いておきましたので、取り出しの参考になればと思います。
マルチフィールドでmt:Loopとmt:Foreach、mt:NestVarタグを使った簡単な例を交えた紹介になります。
これから導入する方はぜひ参考にしてみてください。
明日は取得したマルチフィールドをVue.jsで出力するTipsを紹介したいと思います。
<ClientOnly>
<PostAdSense />
</ClientOnly>