Harry
Harry

Reputation: 321

In ZK, change a component's property from other ViewModel

I have a button in a zul file which is using a ViewModel. I need to disable/enable this button depending on the state of the data in some other zul which is using a different ViewModel. First ZUL file:

<window apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('First VM')" validationMessages="@id('vmsgs')">
<tabbox>
  <tabs>
     <tab label="Label Value" />
  </tabs>
  <tabpanels>
     <tabpanel>
       <include someparameter="${some_VM_model_object}" src="ZUL2"></include>
     </tabpanel>
  </tabpanels>
</tabbox>
<button label="My Button" onClick="" id="mybutton" visible="false" />
</window>

Now there is another ZUL file, and its corresponding VM(Let's say its VM is Second VM) Second VM:

 @AfterCompose
    public void afterCompose(@ContextParam(ContextType.VIEW) Component view) {
        /*In this aftercompose method I want to check some condition on the model of the        
        second zul file and depending on that I want to disable/enable the "My Button"
        button in the  first ZUL*/    
    }

There can be multiple instances of the first zul as well as the second zul, but the related ones can identified through some common data member(which is being passed as "someparameter" in the include component) objects in the ViewModel. Is this possible in ZK or any approach that can help to achieve this ?

Upvotes: 2

Views: 3025

Answers (1)

chillworld
chillworld

Reputation: 4277

I'll show you some awsome feature of ZK.

if your zul2 has a viewmodel in the zul, well do not call this vm!
The reason why is that actually your zul2 has acces to VM of zul 1.
So you can write actually your whole code of Zul2VM just in Zul1VM.

You don't need to, and if zul2 is once used without an include tag, there is no viewmodel included in it so it shall not work properly.

I'll post you here an example and also a link to the fiddle with this code.

First solution:

Index.zul

<window id="win" apply="org.zkoss.bind.BindComposer" viewModel="@id('vm') @init('pkg$.TestVM')">
    <include src="includePage.zul"  />
</window>

IncludePage.zul

<vbox>
    <label value="@load(vm.value)" />
    <button label="Update" onClick="@command('changeValue')" />
</vbox>

TestVM.java

public class TestVM {

    String value = "Default";

    public String getValue () {
        return value;
    }

    @Command
    @NotifyChange("value")
    public void changeValue () {
        value = "new value";
    }
}

Second solution:

Read this documentation.

What does it mean for you :

  1. Give an id to your include(witch react in the doc as a window).
  2. Give Id to your component.
  3. If you have component's what include the interface Idspace in the second zul you need to id them to if there in the tree to your component.
  4. A. Path.getComponent("/zul2/minecomponent"); if there is no IdSpace component between.
  5. B. Path.getComponent("/zul2/IdOfIdSpaceComponent/minecomponent"); if there is IdSpace component between.

If I may make one remark :

Do not use @AfterCompose when using MVVM, that is an annotation for MVC. (I know it works in MVVM)
The right way is to use the @Init annotation. (Where you can also say your superclass has an init to.)

Edit:

Because you still can't get the label, I updated the example in solution 1 with also solution 2.
As you can see I can ask the value from the label out the include.
New fiddle can be found here..

Upvotes: 3

Related Questions