0

How to detach / reattach MVVM windows?

asked 2012-12-20 11:54:46 +0800

cyiannoulis gravatar image cyiannoulis
1201 10

updated 2013-06-28 03:49:10 +0800

jimyeh gravatar image jimyeh
2047 1 4
ZK Team

I really need help with the following scenario. We are migrating an application from MVC to MVVM and i think we are stuck. Any help would be much appreciated. Sample source code at the end of this message.

1. The main-view.zul contains a workspace Div.
2. The main-view creates the 'search-view.zul' with parent the workspace div.
3. The search-view sends the global command 'openDetailView' to the main-view.
4. The main-view detaches the search-view window and creates the 'detail-view.zul' with parent the workspace div.
5. The detail-view sends the global command 'reattachSearchView' to the main-view.
6. The main-view detaches the detail-view window and re-sets the search-view with parent the workspace div.

At this point the search-view.zul stops responding and sends all commands to the main-view generating the following message:
"cannot find any method that is annotated for the command close with @Command in MainViewVM"

I understand that the whole thing has to do with the lifecycle of each viewmodel's binder but i cannot find anything useful in the documentation.
The same functionality could be achieved easily using SelectorComposers and the old data binder.
The only alternative i have found is to make the windows visible/invisible instead of detach/setParent but this is not what we want.

<?page title="Main View" contentType="text/html;charset=UTF-8"?>
<zk>
<window id="winMainView" title="Main View" border="normal" height="100%" width="100%" 
		apply="org.zkoss.bind.BindComposer"	
		viewModel="@id('vm') @init('test.MainViewVM')" >

	<borderlayout>
		<north height="48px" border="none">
			<vlayout>
				<label value="This is the Main View" />
			</vlayout>
		</north>
		
		<center border="none">
			<div id="divWorkspace" vflex="true" />
		</center>
	</borderlayout>
</window>
</zk>

package test;
import org.zkoss.bind.annotation.AfterCompose;
import org.zkoss.bind.annotation.ContextParam;
import org.zkoss.bind.annotation.ContextType;
import org.zkoss.bind.annotation.GlobalCommand;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.select.Selectors;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zul.Div;
import org.zkoss.zul.Window;

public class MainViewVM {
	
	@Wire 
	private Div divWorkspace;
	
	/*
	 * The window representing the 'search' sub-view 
	 */
	private Window wSearchView;
	
	/*
	 * The window representing the 'detail' sub-view 
	 */
	private Window wDetailView;
	
	@AfterCompose
	public void init(@ContextParam(ContextType.VIEW) Component view)
	{
		Selectors.wireComponents(view, this, false);
		
		/*
		 * create the search-view
		 */
		wSearchView = (Window) Executions.createComponents("/test/search-view.zul", divWorkspace, null);
	}
	
	@GlobalCommand
	public void openDetailView() {
		wSearchView.detach();
		wDetailView = (Window) Executions.createComponents("/test/detail-view.zul", divWorkspace, null);
	}
	
	@GlobalCommand
	public void reattachSearchView() {
		wDetailView.detach();
		wSearchView.setParent( divWorkspace );
	}
}

<?page title="Search" contentType="text/html;charset=UTF-8"?>
<zk>
<window id="winSearch" title="Search" border="normal"
		apply="org.zkoss.bind.BindComposer"	
		viewModel="@id('vm') @init('test.SearchViewVM')" >
	
	<vlayout>
		<label value="This is the 'search' view embedded inside the main div" />
		<button label="Close 'search' view and open the 'detail' view" onClick="@command('close')" />
	</vlayout>
</window>
</zk>

package test;
import org.zkoss.bind.BindUtils;
import org.zkoss.bind.annotation.Command;

public class SearchViewVM {
	
	@Command
	public void close() {
		BindUtils.postGlobalCommand(null, null, "openDetailView", null);
	}

}

<?page title="Detail" contentType="text/html;charset=UTF-8"?>
<zk>
<window id="winDetail" title="Search" border="normal"
		apply="org.zkoss.bind.BindComposer"	
		viewModel="@id('vm') @init('test.DetailViewVM')" >
	
	<vlayout>
		<label value="This is the 'detail' view embedded inside the main div" />
		<button label="Close 'detail' view and try to re-attach the 'search view" onClick="@command('close')" />
	</vlayout>
</window>
</zk>

package test;
import org.zkoss.bind.BindUtils;
import org.zkoss.bind.annotation.Command;

public class DetailViewVM {
	
	@Command
	public void close() {
		BindUtils.postGlobalCommand(null, null, "reattachSearchView", null);
	}
	
}

thanks to all
/costas

delete flag offensive retag edit

22 Replies

Sort by ยป oldest newest

answered 2014-04-21 04:46:08 +0800

hawk gravatar image hawk
3250 1 5
http://hawkphoenix.blogsp... ZK Team

Use a `<include> in your workspace might solve your problem.

<include src="@load(vm.currentView)"/>

By changing the attribute vm.currentView to search-view.zul or detail-view.zul, you can make components detach.

link publish delete flag offensive edit

answered 2014-04-22 10:17:26 +0800

cyiannoulis gravatar image cyiannoulis
1201 10

updated 2014-04-22 10:20:04 +0800

@hawk Thanks for your tip but the problem with this approach is that there is no state. Every time you are switching the "currentView" the related page will be reloaded.

I have to say that since the first post of this question we have built a small framework to handle efficiently these issues. In a few words, we are hiding the current window every time a new one is added to the 'workspace'. If the user closes the 'current' window, the main controller pops the previous window from the stack and changes its visibility to true again.

I think some kind of such a framework is still missing from the ZK core. I hope i will find the time to post a complete sample to the community although i think that most of the people here have already implemented some kind of solution.

/costas

link publish delete flag offensive edit
Your reply
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow

RSS

Stats

Asked: 2012-12-20 11:54:46 +0800

Seen: 450 times

Last updated: May 27 '16

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More