同じ処理を何回もさせることができます。forEach属性にオブジェクト集(コレクション)を指定することで、ディベロッパーは関連している要素の処理回数を決めます。便宜上、要素がforEach属性に指定される場合、その要素を繰り返し要素と呼びます。
以下の例でリスト項目は三回作成されます。集合を指定するのに、EL表記を使わなければなりません。
<listbox>
<zscript>
grades = new String[] {"Best", "Better", "Good"};
</zscript>
<listitem label="${each}" forEach="${grades}"/>
</listbox>
繰り返す方式はforEach属性の指定された値のタイプによって違います。
値がjava.util.Collection場合、コレクションのそれぞれの要素に処理が繰り返されます。
値がJava.util.Map場合、それぞれマップのMap.Entryに処理が繰り返されます。
値がJava.util.Iterator場合、iteratorにある要素に処理が繰り返されます。
値が、java.utilEnumeration場合、一覧表のそれぞれの要素に処理が繰り返されます。
Object[]、Int[]、short[]、byte[]、char[]、char[]、float[]、double[]が指定される場合、配列のそれぞれの要素に繰り返されます。
nullの場合、何も生成されません(無視されます)。
上のタイプのどれにもあてはまらない場合、一項目のみであるように、関連した要素は一度だけ処理されます。
<listbox>
<listitem label="${each}" forEach="grades"/>
</listbox>
処理中、eachと呼ばれる変数は作成され、指定されたコレクションの項目に指定されます。上の例では最初の繰り返し処理の中で、eachにBestが指定されて、次にBetterが指定され、最後にGoodが指定されます。
each変数はEL表記とzscriptどちらを使っても参照することができます。each変数の値は一度定義されたら、ZKはそれを関連要素の処理が終わるまで保存します。
forEachStatus変数はorg.zkoss.ui.util.ForEachStatusのインスタンスです。現在の繰り返し処理についての情報を持っています。主に、forEach属性に指定された括弧でくくられた要素の項目を取得します。
以下の例では入れ子状態の繰り返しを使い、二つのリストボックスを生成します。
<hbox>
<zscript>
classes = new String[] {"College", "Graduate"};
grades = new Object[] {
new String[] {"Best", "Better"}, new String[] {"A++", "A+", "A"}
};
</zscript>
<listbox width="200px" forEach="${classes}">
<listhead>
<listheader label="${each}"/>
</listhead>
<listitem label="${forEachStatus.previous.each}: ${each}"
forEach="${grades[forEachStatus.index]}"/>
</listbox>
</hbox>

forEachStatus変数はEL表記とzscriptどちらを使っても参照することができます。.
イベントリスナ中でforEachとforEachStatusを使うことは、コンポーネント作成段階[32]でのみ使用可能なので注意を払わなければなりません。こうして、以下の例は正しくありません。onClickリスナが呼び出されると、each変数が使えなくなります。
<window title="Countries" border="normal" width="100%">
<zscript><![CDATA[
String[] countries = {
"China", "France", "Germany", "United Kindom", "United States"};
]]></zscript>
<hbox>
<button label="${each}" forEach="${countries}"
onClick="alert(each)"/> <!-- incorrect!! -->
</hbox>
</window>
同じ段階(コンポーネント作成段階)で行われるので、ボタンのラベルは正確に指定されています。
また、イベントリスナ中でEL表記を使うことはできません。例えば、OnclickリスナはJavaコードではないので以下のコードは実行失敗してしまいます。(つまり、EL表記はzscript中で無視されます。)
<button label="${each}" forEach="${countries}"
onClick="alert(${each})"/> <!-- incorrect!! -->
each(とforEachStatus)のコンテンツをどこかに保存すれば問題は解決します。保存したコンテンツはリスナ実行中でも使用可能です。また、コンテンツはどこでも保存可能ですが、以下のようにするとわかりやすいです。
<window title="Countries" border="normal" width="100%">
<zscript><![CDATA[
String[] countries = {
"China", "France", "Germany", "United Kindom", "United States"};
]]></zscript>
<hbox>
<button label="${each}" forEach="${countries}"
onClick="alert(self.getAttribute("country"))">
<custom-attributes country="${each}"/>
</button>
</hbox>
</window>
ボタンラベルのように、custom属性のプロパティはコンポーネント作成段階で処理され、そこでeachを使うことができます。eachはcustom属性に保存され、コンポーネントが存在する限り(又は、プログラム上で削除されなければ)なくなりません。