マクロコンポーネントはorg.zkoss.zk.ui.ext.DynamicPropertiedインターフェースを実装します。
つまりgetDynamicPropertyメソッドを以下のように使うことでそのプロパティと通信できます。
<username id="ua" who="John"/> <button label="what?" onClick="alert(ua.getDynamicProperty("who"))"/>
明らかに、DynamicPropertiedの使用は退屈です。
その上、setDynamicPropertyを使用してプロパティを変更しても、マクロの子コンポーネントは変更されません。
例えば、以下のコードはまたusernameとしてMaryではなくてJohnを表示します。
<username id="ua" who="John"/> <zscript> ua.setDynamicProperty("who", "Mary"); </zscript>
どうしてでしょうか?マクロコンポーネントが作成された時、マクロコンポーネントのすべての子コンポーネントは作成されます。
手動58で処理しない限り、変更されません。こ
のため、setDynamicPropertyの起動はマクロコンポーネントの中に保存されたプロパティのみに影響します。Textboxのコンテンツは変更されません。
このため、直接コンポーネントを処理するsetWhoのようなメソッドを提供したほうがいいです。
自分の方法を適用するのに、マクロコンポーネントにクラスを実装し、コンポーネントコマンドのclass属性に指定しなければなりません。
【ヒント】:現在のプロパティを使用して子コンポーネントを再作成するのに、recreateメソッドを使用します
。このメソッドは、すべての子コンポーネントを切り離し、新たに作成します。
クラスを実装する方法は二つあります。その詳細は以下のセクションで説明されます。
マクロコンポーネントに追加メソッドを使用するのに、二つのステップがあります。
1. zkoss.zk.ui.HtmlMacroComponentクラスを拡張する事でクラスを実装します。
//Username.java package mypack; public class Username extends HtmlMacroComponent { public void setWho(String name) { setDynamicProperty("who", name); //arg.who requires it final Textbox tb = (Textbox)getFellow("mc_who"); if (tb != null) tb.setValue(name); //correct the child if available } public String getWho() { return (String)getDynamicaProperty("who"); } }
上に説明したように、マクロコンポーネントが子コンポーネントを作成時に使用される${arg.who}は(${arg.who})マクロページ中で参照されるので、setWhoの中でsetDynamicPropertyを呼びださなければなりません。
setWhoメソッドはマクロコンポーネントが子コンポーネントを作成する前に呼び出される可能性もあるので、mc_whoが存在しているかどうか確認しなければなりません。
mc_whoのsetValueが呼び出されたので、コンテンツとクライアントでの視覚表現はsetWhoが呼び出されたとき自動的に更新されます。
2. クラス属性を使用してマクロ宣言中でクラスを宣言します。
<?component name="username" macroURI="/WEB-INF/macros/username.zul" class="mypack.Username"?>
Javaファイルで実装するのに加えて、zscriptでJavaクラスを実装できます。
メリットはコンパイル不要と、そのコンテンツを動的に(ウェブアプリケーションを再びデプロイすることなく)変更できることです。
デメリットはパフォーマンスが落ちる事と、間違いやすいことです。
ZscriptでJavaクラスを実装するのに、いくつかステップをとります。
1.
例えば、実装するクラスへ/zs/username.zsのようなzscriptファイルを準備しなければなりません。
同じzscriptファイルの中で複数のクラスとファンクションを入れることができます。
//username.zs package mypack; public class Username extends HtmlMacroComponent { public void setWho(String name) { setDynamicProperty("who", name); Textbox tb = getFellow("mc_who"); if (tb != null) tb.setValue(name); } public String getWho() { return getDynamicProperty("who"); } }
2. initコマンドを使用して、zscriptファイルを読み込みます。そして、コンポーネントを宣言します。
<?init zscript="/zs/username.zs"?> <?component name="username" macroURI="/WEB-INF/macros/username.zul" class="mypack.Username"?>
実装クラス(前の例中でmypack.Username)はマクロコンポーネントを本当に使用するのと同じぐらいタイミングで解析されます。
そのため、zscript要素を使用してzscriptファイルを処理するのはOKです。
<?component name="username" macroURI="/WEB-INF/macros/username.zul" class="mypack.Username"?> <zk> <zscript src="/zs/username.zs"/> <username/> </zk>
主観的な意見ですが、initコマンドのほうがわかりやすいと思います。
他のコンポーネントのように、use属性を使用して、どんな特別なインスタンスのマクロコンポーネントを実装するクラスでもオーバーライドできす。
<?component name="username" macroURI="/WEB-INF/macros/username.zul" class="mypack.Username?> <username use="another.MyAnotherUsername/>
もちろん、上の例でanother.MyAnotherUsernameを提供しなければなりません。方法としては、独立したJavaファイルを使用するか、zscriptを使用して実装します。
手動でマクロコンポーネントを作成するのに、以下のようにすべての初期化が終わった後にafterComposeを呼び出さなければなりません。
HtmlMacroComponent ua = (HtmlMacroComponent) page.getComponentDefinition("username", false).newInstance(page); ua.setParent(wnd); ua.applyProperties(); //apply properties defined in the component definition ua.setDynamicProperty("who", "Joe"); ua.afterCompose(); //then the ZUML page is loaded and child components are created
【メモ】:getComponentDefinition メソッドはページ中で定義されたコンポーネント定義を探します。
以下はマクロにUsernameのようなクラスを実装する例です。
Username ua = new Username(); ua.setWho("Joe"); ua.setParent(wnd); ua.afterCompose();
[58] 一方、 include コンポーネントでインクルードされた子コンポーネントはレンダーリング段階で生成されます。それに加え、全ての子コンポーネントは include コンポーネントが評価を外される毎に除去と生成がおこなわれます。