マークアップでウィジェットを記述
もう一つの方法は、テンプレートのHTMLにウィジェットを生成するためのマークアップを記述する方法です。そのためには、コンポジット・ウィジェットのプロパティーで、widgetsInTemplateをtrueに設定する必要があります。この設定により、テンプレートからウィジェットのインスタンスのHTMLを生成する際に、Dojoのパーサーによってテンプレートに記述されたマークアップから自動的にウィジェットが生成されるので、ウィジェットの生成のためのJavaScriptコードが不要になり、ウィジェットの実装が簡略になります。
前回の記事でもご紹介したテンプレートのパラメーター記法により、コンポジット・ウィジェットのパラメータを受け渡すことも可能ですが、ウィジェットの生成ロジックが複雑な場合には限界があります。
上記のJavaScriptによる動的な生成と同等なマークアップによる実装は以下の通りです。
<div> <div> <textarea dojoType="dijit.form.Textarea" cols="${commentColumn}"> </textarea> </div> <div> <input dojoType="dijit.form.TextBox" placeHolder="${nameMessage}"/> <button dojoType="dijit.form.Button">${submitMessage}</button> </div> </div>
dojo.declare("examples.widget.CommentForm", [dijit._Widget, dijit._Templated], { // テンプレートHTMLの指定 templateString: dojo.cache("examples.widget", "templates/CommentForm.html"), widgetsInTemplate: true, // 配下のウィジェット用のパラメーター commentColumn: "30", nameMessage: "お名前を入力してください", submitMessage: "コメント送信" });
ウィジェット動作の実装
さて、ここまででウィジェットの外見は作成できましたので、次にこのコンポジット・ウィジェットの動作を実装することにしましょう。
コンポジット・ウィジェットでは、アプリケーションの動作の実装(コントローラー)の一部をコンポジット・ウィジェットのコードにカプセル化することができます。これによって、外見だけでなく、動作を含めた実装を再利用したり、保守することが容易になります。このコメント送信ウィジェットの場合は、コメントと名前が入力されたことを確認して、サーバーに送信する動作を実装します(サンプル・コードでは、サーバーに送信する部分は省略します)。
テンプレートにマークアップで記述する場合は、配下のウィジェットにdojoAttachPoint属性を指定して、コンポジット・ウィジェットのプロパティーとしてアクセスできるようにしておきます。また、コンポジット・ウィジェットの関数をdojoAttachEvent属性で指定しておくことで、イベント処理関数の呼び出しも簡単に設定できます。JavaScriptコードで動的に生成する場合は、生成時にイベント処理関数を設定しておきます。
_submit: function(){ var comment = this._commentArea.get("value"); if(!comment){ this._showMessage("コメントを入力してください。"); return; } var name = this._nameBox.get("value"); if(!name){ this._showMessage("お名前を入力してください。"); return; } // ここでコメントをサーバーに送信 this._showMessage(name + "さんのコメントを送信しました。"); }, _showMessage: function(message){ if(!this._messageDialog){ this._messageDialog = new dijit.Dialog({title: "コメント送信"}); } this._messageDialog.set("content", message); this._messageDialog.show(); }
<div> <div> <textarea dojoType="dijit.form.Textarea" dojoAttachPoint="_commentArea" cols="${commentColumn}"> </textarea> </div> <div> <input dojoType="dijit.form.TextBox" dojoAttachPoint="_nameBox" placeHolder="${nameMessage}"/> <button dojoType="dijit.form.Button" dojoAttachEvent="onClick: _submit" >${submitMessage}</button> </div> </div>
上記の動作の実装には、Dialogウィジェットを使って、メッセージを表示するようにしています。コンポジット・ウィジェットには、このような補助的なウィジェットの生成や管理の機能を含めることも可能です。
初期の表示には必要なく、ユーザーの操作によって必要になるDialogなどのウィジェットは、コンポジット・ウィジェットの生成時に同時に作成したり、同じテンプレート内に記述しておくことも可能ですが、初期生成のための処理やリソースを軽減するメリットがあるので、必要になった時点で生成する方法がお勧めです。
この例のコメント送信ウィジェットは単純なレイアウトですが、コンポジット・ウィジェットのサイズ変更に伴って配下のウィジェットのレイアウトを最適化するためには、BorderContainerのようなレイアウト用ウィジェットを利用するか、独自のレイアウト処理を実装する必要があります。レイアウト処理については後続の記事であらためてご紹介します。
通常テンプレート内では、ウィジェットの再利用という観点から、原則として、ウィジェットやHTML要素のid属性は指定しません(同一ページで複数インスタンスを利用する際のidの重複を避けるため)。ただし、label要素のfor属性に対象となるウィジェットやinput要素のidを指定したり、TooltipウィジェットやMenuウィジェットを結びつける場合などに、明示的にidを指定する必要がでてきます。その場合は、コンポジット・ウィジェットのidに特定の文字列を付加するというコンベンションでテンプレート内のウィジェットや要素にユニークなidを割り当てることができます。
<label for="${id}_nameBox">お名前:</label> <input id="${id}_nameBox" dojoType="dijit.form.TextBox"/>