カスタム・ウィジェットの作成例
それでは、実際にライフサイクル・メソッドを意識しながら、カスタムウィジェットを作成してみましょう。個人の名前、所属、メールアドレス、写真などの情報を、画面上に名刺っぽく表示するプロフィール・カード・ウィジェットを、順を追って作っていきます。
テンプレート
まず「ライフサイクル・メソッドをどのように実装していくのか」とは直接関係はないのですが、カスタム・ウィジェットを実装する上で非常に重要な機能である、ウィジェットのテンプレート機能を説明します。同時にカスタム・ウィジェットのコードがどのような構成になるのかも簡単に説明します。
与えられたデータ(プロパティ)を、HTMLで名刺っぽく表示するというウィジェットを考えます。非常に単純な例ですが、データをどのようにHTMLとして表示するかという、Webアプリケーションとして最も基本的な機能です。
こういったことを容易に実現するため、Dojoはテンプレート・システムを備えています。これを利用するためにはウィジェットのベースクラスであるdijit._Widget以外にdijit._Templatedを継承する必要があります。以下がウィジェットのソースコードです。
1: dojo.provide("examples.widget.ProfileCard1"); 2: dojo.require("dijit._Widget"); 3: dojo.require("dijit._Templated"); 4: dojo.declare("examples.widget.ProfileCard1", [dijit._Widget, dijit._Templated], { 5: //テンプレートファイルの読み込み 6: templateString: dojo.cache("examples.widget", "templates/ProfileCard1.html"), 7: 8: // ${}を用いてテンプレート内で以下のプロパティを参照する 9: //プロフィールカードのタイトル 10: title: "", 11: //社員氏名 12: name: "", 13: //メールアドレス 14: email: "", 15: //所属 16: organization: "", 17: // プロフィール用画像のファイルパス 18: src: "", 19: //詳細情報 20: detail: "" 21: } 22:);
1行目のdojo.provide()で、指定した名前(examples.widget.ProfileCard1)でDojoのパッケージ・システムに登録します。ファイルはパッケージの名前に従ったディレクトリ構成に置く必要があります。この例では、examples/widget/ProfileCard1.jsというディレクトリ構成にします。このウィジェットを使用する場合、この名前でdojo.requireすることになります。
2-3行目で、このウィジェットが参照する全てのパッケージをdojo.require()で宣言します。
4-15行目のdojo.declare()でウィジェットを宣言します。第1引数がクラス名、第2引数が継承する親クラスの配列、第3引数がprototypeにコピーされるプロパティで、クラス定義のメインとなる部分です。ここでは、ウィジェットのベース・クラスであるdijit._Widgetとテンプレートを使うためのdijit._Templatedを継承しています。カスタム・ウィジェットの多くはこれら2つのクラスを継承する、もしくは、例えばdijit.form.Buttonのように既存のウィジェットを継承することになります。親クラスが既にdijit._Widgetなどを継承している場合は、それらをここに指定する必要はありません。
dijit._Templatedはテンプレート用のプロパティtemplateStringを持っており、上記の例では"templates/ProfileCard1.html" を参照しています。それではその中身を見てみましょう
<div class="dijitDialog dijitDialogFixed" style="position:relative; width:300px;"> <div class="dijitDialogTitleBar"> <div class="dijitTitlePaneTitleFocus">${title}</div> </div> <div> <div style="width: 80px; float: left; margin-left: 10px;"> <img width="80" height="80" src="${src}"></img> </div> <div style="margin: 5px 5px 5px 100px;"> <div style="padding: 5px;"><span>名前:</span><span>${name}</span></div> <div style="padding: 5px;"><span>所属:</span><span>${organization}</span></div> <div style="padding: 5px;"><span>メール:</span><span>${email}</span></div> <div style="padding: 5px;"><span>詳細:</span><span>${detail}</span></div> </div> </div> </div>
テンプレートとしてHTMLの一部(フラグメント)を記述している様子がわかると思います。名前、所属などの可変な値は${プロパティ名}として記述しておくことにより自動的に埋め込まれます。ではこのウィジェットを表示させてみましょう。表示用のHTMLは以下のようになります。
<script type="text/javascript"> dojo.registerModulePath("examples", "../../examples"); dojo.require("dojo.parser"); dojo.require("examples.widget.ProfileCard1"); </script> ... <div dojoType="examples.widget.ProfileCard1" title="社員プロフィール" email="keisuke.aoki@email.com" name="青木 圭介" src="./images/employee001.png" detail="こんにちは、人事部の青木です。主に新卒採用を担当しています。" organization="人事部"></div>
まず、scriptタグの中でdojo.registerModulePath("example", "../../examples");のようにモジュールの存在場所をdojo.jsからの相対位置で指定し、dojo.requireでexamples/widget/ProfileCard1.jsをロードします。
次にdivタグのdojoTypeでクラス名を指定し、title、nameなどの必要なプロパティはdivタグの属性として定義します。
これをブラウザ上で表示させると以下のようになります。
Dojoのテンプレートには、${プロパティ値}による埋込み以外にも便利な機能があります。一つはdojoAttachPointです。例えば、テンプレートのタグ内にdojoAttachPoint="foo"のように記述しておくと、自動的にその要素(HTML要素の場合はDOMノード、ウィジェットの場合はそのインスタンス)がウィジェットの中でプロパティとしてアクセスできるようになります。もうひとつはdojoAttachEventです。例えば、テンプレート内のボタンなどにdojoAttachEvent="onClick: doSomething"と記述しておくと、イベント・ハンドラが自動的に紐付けられます。また、テンプレートの中にはHTML以外にウィジェットを含めることができます。その場合は、カスタムウィジェットのプロパティwidgetsInTemplateをtrueにセットしておきます。また、これは忘れがちなのですが、テンプレート内で使用するウィジェットは、カスタムウィジェット内でdojo.requireしておく必要があります。