0

Why I'm using a ViewModel and not a Composer for everything

asked 2012-11-15 14:01:50 +0800

rickcr gravatar image rickcr
704 7

Since no one seems to be following up in this thread http://www.zkoss.org/forum/listComment/18752-Event-Queue-subscribed-more-than-once, I'll briefly explain the issue.

When trying to use an MVVM pattern, you often see suggestions to use Composers for things where you are dealing more directly with the UI elements (the idea being that ViewModels shouldn't know about a UI elements.

However in order for a ViewModel to notify a Composer of an event, you can't just listen for a regular global command, it has to subscribe to a queue with a listener and your ViewModel has to send out a global command to that queue.

From the above thread though this seems to have a lot of messy issues with having to clean up listeners, whereas instead of using a Composer I just use a ViewModel I don't have those issues. In fact the ViewModel code and the Composer look almost identical.

Am I taking the wrong approach here?

As an example (real life one that I ran into), think of your navigation controller that might open and close new windows. It works fine as a regular Composer to start with, but what if you need another ViewModel to trigger that Composer fire and open a page? You have to create a queue in order to notify it. Now if you refresh the page you have multiple instances of listeners unless you handle complicated clean up routines. Vs instead I just use a ViewModel on top of my navigation and I can listen for a globalCommand:

//use by the navigation menu clicks
@Command
public void onNavigate(@BindingParam("page") String page) {
     //code to open the correct page
}

//called from external view models
@GlobalCommand
public void switchPage(@BindingParam("page") String page) {
	onNavigate(page);
}

With a Composer handling this you'd need

@Subscribe("navigationQueue")
public void switchPage(Event event) {
    //....
}

Bottom line is I don't see what advantage I get not using ViewModels for everything.

delete flag offensive retag edit

25 Replies

Sort by ยป oldest newest

answered 2012-11-22 16:48:37 +0800

rdgrimes gravatar image rdgrimes
735 7

updated 2012-11-22 17:03:23 +0800

@rickr:

"I did read your comment "I chose not to go with MVVM for the portal container itself due to its heavy involvement with dynamically creating, updating, and destroying its child components." and that's interesting- you must know a lot more about what's going on 'under the hood' than I do since I wasn't aware of all that."

No, I didn't mean the MVVM does all that, I meant the business portal is doing all that, which is why I use MVC over MMVM for the portal portion. Hope that's clearer.

@czynga:

The afterCompose doesn't break the MVVM pattern, since they included an @AfterCompose annotation specifically for MVVM, which is executed in the BindComposer's doAfterCompose method.

@Senthilchettyin:

Per the documentation for the Window component:

"onClose is sent when the close button is pressed (if isClosable() is true). The window has to detach or hide the window. By default, onClose() detaches the window. "

So, I'm not sure why you need to go to extraordinary means to detach the window. Seems like, when you close a Window, it detaches automatically from the parent.

link publish delete flag offensive edit

answered 2012-11-23 02:17:23 +0800

Senthilchettyin gravatar image Senthilchettyin flag of India
2623 3 8
http://emrpms.blogspot.in...

Hi
rdgrimes

For the end user, in the modal window, i have placed explicit close button to close the current screen and back to the listing window. So how i can do this in MVVM.

You can check here.

link publish delete flag offensive edit

answered 2012-11-23 08:26:11 +0800

terrytornado gravatar image terrytornado flag of Germany
9393 3 7 16
http://www.oxitec.de/

What Senthil means is: Where is the place in a MVVM to call programatically a myWindow.onClose();

link publish delete flag offensive edit

answered 2012-11-23 11:07:30 +0800

Senthilchettyin gravatar image Senthilchettyin flag of India
2623 3 8
http://emrpms.blogspot.in...

updated 2012-11-23 11:09:23 +0800

Yes. Thanks Stephan for converting into simple

Please check this also

link publish delete flag offensive edit

answered 2012-11-23 16:52:44 +0800

rdgrimes gravatar image rdgrimes
735 7

updated 2012-11-23 17:04:49 +0800

@terrytornado, @Senthilchettyin:

I really don't know what you're looking for because you don't need to call myWindow.onClose(). Per the Window source:

	/** Process the onClose event sent when the close button is pressed.
	 * <p>Default: detach itself.
	 */
	public void onClose() {
		detach();
	}

Further, the documentation makes it clear that you don't need to send the onClose event, but the clicking of the close button automatically sends the onClose event so that the above cited method is invoked:

"Once the user clicks on the close button, an onClose event is sent to the window which is processed by the onClose method of the Window component. Then, onClose, by default, detaches the window itself." - source

And, since Senthichettyin stated previously he supplied a close button in the modal window so the user could click it, there is no need to call onClose() explicitly. The user's action will cause the detach to occur.

link publish delete flag offensive edit

answered 2012-11-23 18:16:16 +0800

Senthilchettyin gravatar image Senthilchettyin flag of India
2623 3 8
http://emrpms.blogspot.in...

Hi

I dont think so we are all in the same page. Rdgrimes, We are NOT talking about the default close button in the top right corner of the window with X Mark. (This will appear when you set closable property (Window.setClosable(boolean)) to true.

All we are asking, how to close the current window by clicking button using button component using MVVM.

Just a small example, in any typical crud window, we will always have save and cancel button in the bottom, so that either user can enter the information in the
window and click save button , or they can simple cancel the operation and back to the listing window.


Regards
Senthil M

link publish delete flag offensive edit

answered 2012-11-23 18:27:20 +0800

rdgrimes gravatar image rdgrimes
735 7

updated 2012-11-23 18:42:54 +0800

So, are you asking how to close the window after the save button is clicked? If so, why can't you, in the save button @command:

onClick="@command('save', target=self)"

Then, in your viewmodel's save method, you have access to the self component via:

@Command
public void save(@BindingParam("target")Component target){
}

I haven't tested it, but you should be able to access target or an ancestor of target (whichever ancestor is the actual Window component), casting it to Window, and execute its detach method.

link publish delete flag offensive edit

answered 2012-11-23 20:01:47 +0800

rickcr gravatar image rickcr
704 7

@Senthilchettyin, maybe I'm missing the obvious and I might not undertand exactly what you mean? Do you mean you want to explicitly close a window from you ViewModel?

I do that by binding the window in my ViewModel with @Wire

for example I have a popup window definedi in my zul and I want the viewmodel to close it after the user does "search"...

@Wire("#catFilterPopup")
protected Popup catFilterPopup;


@AfterCompose
public void afterCompose(@ContextParam(ContextType.VIEW) org.zkoss.zk.ui.Component view){
	Selectors.wireComponents(view, this, false);
}

@Command
public void search() {
     //do stuff
    catFilterPopup.close();
}

In your case if you want to close the entire window that is bound by the ViewModel, did you try wiring the window id like I do above with the Popup? I'd think it would behave the same way but I haven't tried. Just bind the window by id then manually close it where you want in the ViewModel?

link publish delete flag offensive edit

answered 2012-11-23 20:50:48 +0800

terrytornado gravatar image terrytornado flag of Germany
9393 3 7 16
http://www.oxitec.de/

updated 2012-11-23 20:52:41 +0800

I do that by binding the window in my ViewModel with @Wire

Does this not brokes the MVVM paradigm?

link publish delete flag offensive edit

answered 2012-11-23 21:14:37 +0800

rdgrimes gravatar image rdgrimes
735 7

updated 2012-11-23 21:16:01 +0800

@rickr, terrytornado:

The ZK team recommends against rickr's approach. See link

"Although the design principle of MVVM pattern is that ViewModel should not have any reference to UI components, ZK still provides two ways to retrieve UI components in a ViewModel. However, we do not suggest this usage as it loses ViewModel an important advantage: loose coupling with View. Notice that binder also manipulates UI components, so your operation to UI components may affect binder's work. Please be careful when using it."

Instead, the proper way to do it is as I detailed in my previous post (passing a reference of self or an ancestor thereof via the @command, which is then received as a binding parameter in the vm method).

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-11-15 14:01:50 +0800

Seen: 552 times

Last updated: Dec 07 '12

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