How to Use each and forEachStatus Variables in Event Listeners

It is a bit tricky to use the forEach and forEachStatus variables in event listeners, because they are available only in the Component Creation Phase[34]. Thus, the following sample is incorrect: when the onClick listener is called, the each variable is no longer available.

<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>

Notice that the button's label is assigned correctly because it is done at the same phase – the Component Creation Phase.

Also notice that you cannot use EL expressions in the event listener. For example, the following codes fail to execute because the onClick listener is not a legal Java codes (i.e., EL expressions are ignored in zscript).

<button label="${each}" forEach="${countries}"
        onClick="alert(${each})"/> <!-- incorrect!! -->        

A Solution: custom-attributes

The solution is that we have to store the content of each (and forEachStatus) somewhere such that its content is still available when the listener executes. You can store its content anywhere, but there is a simple way to do it as follows.

<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(&quot;country&quot;))">        
            <custom-attributes country="${each}"/>            
        </button>        
    </hbox>    
</window>

Like button's label, the properties of custom attributes are evaluated in the Component Creation Phase, so you can use each there. Then, it is stored to a custom attribute which will last as long as the component exists (or until being removed programmingly).



[34] Refer to the Component Lifecycle chapter for more details.