Use Java

Every ZUL component has its mapping Java class. Every ZUL element declared in ZUML has its mapping Java object. You can easily access the object in Java code if you assign it an id. The org.zkoss.zk.ui.Path class provides utilities to simplify the location of a component among ID spaces. Its usage is similar to java.io.File. Like a path in a file system, a component path is a catenation of IDs of components along ID spaces.

By default, the root of a component path is the current page. If you want to identify another page, you have to use //. Note that elements that can be space owners (those component classes that implement org.zkoss.zk.ui.IdSpace) such as page. Tip: Path.getComponent("//xyz") always returns null, since the identifier following // is the page’s ID. And, the page is not a component. window, include, and regular macro. (Note: Components on an include-page are not accessible with the same path expression as if they were on the containing page.)

Path.getComponent("//P/A/B/D"); // since C is not a spaceOwner, we don't have to go through C.
Path.getComponent("/A/B/D"); // assume the current page is P, then you can omit //P

For example, if you have a label in ZUML as below:

<?page id="P"?>
<window id="A">
  <window id="B">
    <div id="C">
      <label id="D"/>
    </div>
  </window>
</window>

Then, you can access it as a Java object by retrieving it through Path.getComponent():

Label label = (Label) Path.getComponent("//P/A/B/D");

Use zscript

It’s intuitive to access ZUL elements in zscript.

<window>
  <label id="lab_1" value="initial by label"/>
  <zscript>
    lab_1.value = "changed by zscript";
  </zscript>
</window>

The result will show:

changed by zscript

But you have to pay attention to the declaration sequence because zscript is evaluated when a ZUML page is rendered. Typical use of zscript includes initialization and declaring global variables and methods.

If we adjust the sequence of the previous example:

<window>
  <zscript>
    lab_1.value = "changed by zscript";
  </zscript>
  <label id="lab_1" value="initial by label"/>
</window>

The result will show:

initial by label

Notice the namespace is hierarchical. That means components from upper id space are accessible unless overridden. But components in lower id space are not accessible. Therefore, in the following example, zscript inside window win_1_1 can access lab_1:

<window id="win_1">
  <label id="lab_1" value="initial by label"/>
  <window id="win_1_1">
    <zscript>
      lab_1.value = "changed by zscript";
    </zscript>
  </window>
</window>

And the result shows:

changed by zscript

If we modify the namespace structure to:

<window id="win_1">
  <window id="win_1_1">
    <label id="lab_1" value="initial by label"/>
  </window>
  <zscript>
    lab_1.value = "changed by zscript";
  </zscript>
</window>

The result will be:

initial by label

Just like Java, you can use Path.getComponent in zscript for sure:

<window id="win_1">
  <window id="win_1_1">
    <label id="lab_1" value="initial by label"/>
  </window>
  <zscript>
    public void sayHello() {
      Label l = (Label)Path.getComponent("/win_1/win_1_1/lab_1");
      l.setValue("changed");
    }
  </zscript>
  <button label="ok" onClick="sayHello()"/>
</window>

In the above example, sayHello() is evaluated when the button is clicked. Therefore, it isn’t affected by the declaration sequence.

Use Expression Language

Like zscript, EL has to pay attention to the declaration sequence. In the following example:

<window>
  1:${btn_1.label}
  <button id="btn_1" label="button_1"/>
  2:${btn_1.label}
</window>

The result will show:

1:2:button_1

Like zscript, the namespace is hierarchical. In the following example:

<window id="win_1">
  <label id="lab_1" value="myValue"/>
  1:${lab_1.value}
  <window id="win_1_1">
    1.1:${lab_1.value}
  </window>
</window>

The result will show:

myValue
1:myValue
1.1:myValue

And if we modify the structure to:

<window id="win_1">
  <window id="win_1_1">
    <label id="lab_1" value="myValue"/>
    1.1:${lab_1.value}
  </window>
  1:${lab_1.value}
</window>

The result will be:

myValue
1.1:myValue
1:

Unlike zscript, EL doesn’t accept operator =.

Notes