2

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 ?

Harry
  • 321
  • 4
  • 13

1 Answers1

3

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

chillworld
  • 4,207
  • 3
  • 23
  • 50
  • The first zul is also being included somewhere as a tab, and some parameters are passed to it which are being fetched in the init function through "@ExecutionArgParam("parameter name")".For the second zul also I am passing some parameters in the include statement and these are fetched in the init of second vm and this parameter object becomes the model of the second zul. So can I handle different set of ExecutionArgParam for both the zul in the init of the same VM ? Do I have to set some flag in the int Exec Argument to find which zul has invoked the VM ?is that the right approach ? – Harry Jan 15 '15 at 10:02
  • @Harry The execution params is a map. 2 different names of key is possible. If key not exist you get just a null value. So you could know if the param is not null. – chillworld Jan 15 '15 at 10:26
  • I am not able to get the components of 2nd zul by id in the VM using Selectors.wireComponents – Harry Jan 15 '15 at 13:26
  • do you use solution 1 or 2? – chillworld Jan 15 '15 at 13:39
  • I am using the First solution, in which the same VM is there for both the zuls, and I used your example, but if I give the label in IncludePage.zul some id and then try to access it in TestVM.java, the reference for the Zul Label Object is having null value. – Harry Jan 15 '15 at 15:44
  • @Harry See latest fiddle in the edit part. There is your solution. – chillworld Jan 16 '15 at 07:49
  • @Harry, your welcome, is the answer about iterating differt templates also good or do you have still problems there? – chillworld Jan 16 '15 at 13:48
  • I am using the same VM apprach and I will access the elements of child zul through their ids, will ask u if i have problem there – Harry Jan 19 '15 at 06:23
  • ...I am facing a problem in this approach... I think the init function is called only for the parent zul i.e. zul 1, so the model required for zul 2 i.e. includePage.zul is not prepared as the init portion for this zul is not called. – Harry Jan 22 '15 at 07:01