# Have to have fulfill for a tabPanel fire from a viewModel that sets the selected tab in Java?

rickcr
704 7

Consider three tab panels:

<tabpanel fulfill="tab1.onSelect">
<include id="page1"  src="/page1.zul" ></include>
</tabpanel>
<tabpanel fulfill="tab2.onSelect">
<include id="page2"  src="/page2.zul" ></include>
</tabpanel>
<tabpanel fulfill="tab3.onSelect">
<include id="page3"  src="/pages3.zul" ></include>
</tabpanel>


The above zul is backed by a ViewModel (MVVM pattern.)

page2's ViewModel can fire off a global command "openTab3." The tabbox's view model responds to that global command and then can open up tab 3...

this.selectedTab = 2;


This issue however is that page3.zul is not rendered when I try to load the tab up like this via Java. I want page3 to rendered deferred just as if you had manually clicked on the tab and triggered the fulfill, but I'm not sure how to do this?

(Note, if I remove the fulfill on tab3, it renders fine, but of course it's not deferred which is bad since I only want tab3's content to be initialized if it's truly needed.)

There must be something simple I'm missing?

delete retag edit

## 9 Replies

rickcr
704 7

Is there maybe some kind of "onOpen" type of behavior I can listen for to signal the loading of the page? Surely what I'm trying to accomplish can be done programmatically some how?

I also should have noted in the initial post the tabbox is bound to the selectedTab property of its view model:

<tabbox id="myTabBox" selectedIndex="@bind(myBuilder.selectedTab)" >


But like I mentioned in the initial post, this doesn't trigger the 'fufill' in the same way manually clicking on the tab does.

9373 3 7 16
http://www.oxitec.de/

	/**
* When the tab 'tabCallList' is selected.<br>
* Loads the zul-file into the tab.
*
* @param event
* @throws IOException
*/
public void onSelect\$tabCallList(Event event) throws IOException {

if (tabPanelCallList.getFirstChild() != null) {
tabCallList.setSelected(true);

return;
}

// Check if tab is not created than create and select them
if (tabPanelCallList != null) {

// calls Executions.createComponents...
FHGuiUtils.createTabPanelContent(tabPanelCallList, this, "ModuleMainController", "/WEB-INF/pages/XXXXXXXXX/call/callList.zul");
tabCallList.setSelected(true);
}

}


rickcr
704 7

Thanks Terry. I'm still a bit new and using a ViewModel approach and have some trouble following your code exactly (never mind that I'd need to know how your FHGuiUtils class is creating the content.)

Regardless the idea should be that my view model should be pretty clean. It's frustrating because the code is fine if users click on the tabs, there has to be some way to trigger the "onSelected" of the tabPanel and have it fire what "fulfill" is doing in the code below:

<tabbox id="myTabBox" selectedIndex="@bind(vm.selectedTab)" >
<tabs visible="true">
<tab id="tab1" label="Tab 1"  />
<tab id="tab2" label="Tab 2"  />
<tab id="tab3" label="Tab 3" />
</tabs>
<tabpanels>
<tabpanel fulfill="tab1.onSelect">
<include id="page1"  src="/page1.zul" ></include>
</tabpanel>
<tabpanel fulfill="tab2.onSelect">
<include id="page2"  src="/page2.zul" ></include>
</tabpanel>
<tabpanel fulfill="tab3.onSelect">
<include id="page3"  src="/pages3.zul" ></include>
</tabpanel>
</tabpanels>
</tabbox>


if the tab box view model's property "selectedTab" changes it's value, the tab is correctly switched to, but the included zul is never initialized.

I guess rather than set the selectedTab, I could try to do something like you're doing Terry and programmatically set the tab's content. I'm just not sure how to do this within a View Model or if it's even the correct approach to take.

rickcr
704 7

Terrytornado, I might be stuck having to do something like you are showing. ( A real shame in my opinion since the concept of "fulfill' is there via a true select of the tab through a button click so you wouldn't think, through Java, I could get it to fire.)

But anyway, do you have some example how I could handle what your doing in a view model?

Right now my tabbox view model has some global listeners like...

//myVM
@GlobalCommand
public void showFooBar(){
this.selectedTab = FOO_BAR_TAB_INDEX;
}

//my zul
<tabbox id="myTabBox" selectedIndex="@bind(myVM.selectedTab)" >


I'd somehow inside of MyVM in showFooBar need to create the fooBar.zul and add it to the correct tabPanel, just not sure how to do all this within a ViewModel. At this point I don't even care about polluting the view model. (Although I do wish someone from the support team could help with this since there should be a way to get the separation of concerns working to accomplish this.) [I tend to think what the framework should handle is when something is bound to selectedIndex of a tabbox , the fulfill of a tablpanel that is set to onSelect should still fire. ]

Thanks again for any pointers

hawk
2018 1 5
http://hawkphoenix.blogsp...

Hi, rickcr

on-demand evaluation might solve your problem.
http://books.zkoss.org/wiki/ZK%20Developer's%20Reference/UI%20Composing/ZUML/On-demand%20Evaluation

rickcr
704 7

Hawk that was the first link I looked at, but it doesn't help with the issue I'm having (other than possibly the first link on that page which mentions http://books.zkoss.org/wiki/ZK_Developer%27s_Reference/UI_Composing/ZUML/Load_ZUML_in_Java)

All the examples on the link you posted only seem to work if binding fulfill on the tabbox to things the user could actually click on. Fulfill is never called when the selected tab is triggered by some other means (like I described above. )

Also, I though about binding all the clicks that could trigger the tab change but I can't seem to get that to work when your trying to bind to a click event on a tab that hasn't been rendered yet.

//TRIED
<tabpanel fulfill="tab3.onSelect, page2.someId.onClick"/>
<tabpanel fulfill="tab3.onSelect, tab2.page2.someId.onClick"/>


The problem is no matter what I try above I get null pointers.. probably because page2 is deferred so I can't even bing to an onClick on that page.

hawk
2018 1 5
http://hawkphoenix.blogsp...

Hi rickcr:
The "fulfill" you set is triggered by event, so if you change selection through data binding (MVVM approach). It won't trigger an event to the tab, thus the Tabpanel won't be dynamically created.

You can send an "onSelect" event to tab2 with:

Events.sendEvent("onSelect",tab2,null);


This will trigger "fulfill" work as expected.

But I suggest you to use MVC approach because the feature you want needs fine-grained component and event control. The fine-grained component control is not proper under MVVM approach.

rickcr
704 7

Thanks so much Hawk!

Created a SelectorComposer for my Tabbox and it listens for some global events that could fire from the ViewModels. Not sure if I'm using the most eloquent approach but it's working now...

@Subscribe("builderTabBoxSelectionQueue")
public void showBuilderTab(Event event) {
Tab tab = null;
if(event instanceof GlobalCommandEvent) {
String command = ((GlobalCommandEvent)event).getCommand();
tab = buildingBlocks;
} else if ("productsPage".equals(command)) {
tab = products;
}
}
Events.sendEvent("onSelect", tab, null);
tab.setSelected(true);
}


hawk
2018 1 5
http://hawkphoenix.blogsp...

A better solution.

 <tabpanel fulfill="self.linkedTab.onSelect"> </tabpanel>