0

Notifying ViewModel- how to programmatically cal; command or echoEvent to notify it?

asked 2012-05-18 13:56:21 +0800

rickcr gravatar image rickcr
704 7

How do you handle this in MVVM type of architecture....

user clicks a button... you now when do a few UI specific things (things that don't need to be handled in the ViewModel - eg hide some components), but when your finished doing your UI things you want the ViewModel notified?

All the examples show things like <button onClick="@command('someViewModelMethod')"/>, but what if you need to do other things first before calling that command?

<button id="myButton">
       <attribute name="onClick">
              //do some stuff on the UI 
             //*** Now need to notify a method in my ViewModel
      </attribute>
</button>

I tried doing something like...

<button id="myButton">
       <attribute name="onClick">
              //do some stuff on the UI 
              Events.echoEvent("onCompletedStuff", myWindow, null);
      </attribute>
</button>

Think I could then listen in my view model:

@Listen("onCompletedStuff ")
public void onDoStuff() {
    //...
}

But the onDoStuff of my ViewModel never fires?? I even tried changing the @Listen to @Listen("onCompletedStuff = #myWindow") thinking that might be needed.

I must be missing something basic here and going crazy scouring the docs to try to figure this out... how could I call a @command from my zul or fire a listener on my ViewModel from my zul?

delete flag offensive retag edit

10 Replies

Sort by ยป oldest newest

answered 2012-05-18 19:23:35 +0800

Matze2 gravatar image Matze2
773 7

updated 2012-05-18 19:25:14 +0800

In MVVM, i.e. BindComposer, there is no support for @Listen as far as I know. There is @Command instead.
Why don't you do something like

<button onClick="@command('handleSomething')"></button>
and
@Command
public void handleSomething() {
...
}

Hiding components is explicitly supported in MVVM by binding the visible attribute.

link publish delete flag offensive edit

answered 2012-05-18 21:09:46 +0800

rickcr gravatar image rickcr
704 7

updated 2012-05-18 21:10:22 +0800

In regard to: why don't I try :

<button onClick="@command('handleSomething')"></button>

view model..

@Command
public void handleSomething() {
...
}

Well I was hoping I could call showBusy(..) and then somehow call the long running process method of my ViewModel class, after which I could then call Clients.clearBusy. I was trying to find a way to do this, based on what is shown in the developer doc on page 351 https://img.skitch.com/20120518-p269u7pwkg1ty28m9t1exun23e.jpg


I can't figure out how to do the above with MVVM (get "showBusy" and "clearBusy" to work), but it got me thinking in general how I would do other similar types of things on the client side (zul) and then needing to call a method on the view model (hiding an element might not have been the best example.) Basically a way to call a command manually?

link publish delete flag offensive edit

answered 2012-05-18 21:46:02 +0800

Matze2 gravatar image Matze2
773 7

updated 2012-05-18 21:46:41 +0800

I guess, currently you need to do it with two command methods, e.g. "prepareLongRunningProcess" and "executeLongRunningProcess".
This means, you convert the inline Java (which is an anti-pattern btw; the ZK guys do that just for simplicity in the documentation) into command methods and bind the events onClick and onLater with that two commands above.
Not perfect, but possible.
I am not sure, if you plan to execute some Java parts in ZUL file directly. This is the worst alternative in my humble opinion.

link publish delete flag offensive edit

answered 2012-05-18 22:23:36 +0800

rickcr gravatar image rickcr
704 7

updated 2012-05-18 22:23:53 +0800

Trust me I don't want any java commands in my ZUL and want my zul as clean as possible.

Even with the two command approach I'd still have the issue how to show and hide the "busy" message. I don't want to do that in my ViewModel since that makes the ViewModel start doing UI specific things which it shouldn't do.

I was thinking something like this, if this is even possible...

onClick="Clients.showBusy(...) @command('doLongProces') Clients.clearBusy()"

link publish delete flag offensive edit

answered 2012-05-19 14:49:22 +0800

Matze2 gravatar image Matze2
773 7

I thought you don't want any Java in your ZUL,

With MVVM you can solve many, but not all things with respect to UI. I don't see a big problem with having these two lines of code in ViewModel.
If this is the only software design problem you have, you can count yourself lucky.
Just my two cents.

link publish delete flag offensive edit

answered 2012-05-21 01:53:02 +0800

rickcr gravatar image rickcr
704 7

updated 2012-05-21 01:53:36 +0800

How do I have access to the component names within the ViewModel? I can't seem to find an example of how to get handle to them?
I need to somehow call Clients.showBusy with the component arg that I want to display the "busy" message on eg Clients.showBusy(theWindowComponent, "Busy")

Also am not sure how to chain these two calls within the model="" attribute of my listbox. Currently it looks like

<listbox model="@bind(vm.employees)" selectedItem="@bind(vm.selected)" hflex="true"  >

I want to have a busy spinner showing over the grid while it loads since it might take a while. How would I fire off two commands? The first to load the showBusy() and then the second to return the employees and then hide the showBusy? (After doing a "save" the grid also needs to show the spinner since it will be going to the server again to be sure it gets a fresh list of employees.)

Note also, on a button onClick it seems to only allow one command to be used, so not sure how I'd even fire off two of them. If I tried to echo the Event in my VM I have the same issue as well as trying to get a hold of the component.

Overall, this still seems extremely confusing to implement in MVVM, and I'm hoping someone could provide just a simple example of how to get your typical showBusy working within a MVVM architecture... at this point I don't care even about being a purist... I'm just looking for a solution that someone would take.

With all the Ajax stuff that goes on now and days displaying a "busy" message is a common thing so this issue must come up in other apps?

link publish delete flag offensive edit

answered 2012-05-21 02:20:26 +0800

rickcr gravatar image rickcr
704 7

If anyone wants to mess around with my example, I'm working on a community example that uses MyBatis3.1 / Spring 3.1/ Maven/ and ZK 6. Lots of hibernate stuff but I'm a MyBatis (formerly iBATIS fan) so I''ll be working on a write up and more formal post when I have all these things worked out. I borrows from the ZK Spring app found here http://books.zkoss.org/wiki/Small_Talks/2012/February/MVVM_in_ZK6:_Work_with_Spring

The latest ZK version I'm working can be found here https://github.com/rickcr/employee-maint-spring-mybatis/tree/zk-version but I also just zipped it up here https://www.sugarsync.com/pf/D7754172_2045968_17679

A screen shot of the "processing" you can see shows up in the upper left corner, but I want that processing to be a custom busy message and show up over the grid

https://img.skitch.com/20120521-dngd8r135b955hwrxqwm2h1i5w.jpg

(As I posted in another thread I'd also like to get the "selectedItem" functionality working as well.... right now I'm using some ugliness with selectedIndex.)

link publish delete flag offensive edit

answered 2012-05-21 02:22:09 +0800

rickcr gravatar image rickcr
704 7

Oh and to build it (assuming mvn installed) just run "mvn clean install" and move to your app server. URL would then just be http://localhost:8080/employee-maintenance/

link publish delete flag offensive edit

answered 2012-09-19 08:28:38 +0800

szarza gravatar image szarza
62 2
http://balteus.blogspot.c...

Probably it's too late, but I've found your message now. My solution was using "attribute" attribute to code on the UI, and event to fire @command binding. Like this:

<timer onCreate="self.setDelay(slider.getCurpos() * 1000)" repeats="true" 
	onTimer="@command(tabMonit.selected || tabMonitA.selected ? 'onUpdateServices' : '')">
		<attribute name="onTimer">
			self.setDelay(slider.getCurpos() * 1000);
		</attribute>
</timer>

Regards

link publish delete flag offensive edit

answered 2012-10-03 01:27:29 +0800

samchuang gravatar image samchuang
4084 4

hi, how about this

zul

<window title="Long Operation" border="normal"
	apply="org.zkoss.bind.BindComposer"
	viewModel="@id('vm') @init('mvvm.LongOperationVM')">
	<button label="do Long Operation" onClick="@command('doLongOperation')"></button>
</window>

java

public class LongOperationVM {

	@Command
	public void doLongOperation(final @ContextParam(ContextType.COMPONENT) Component component) {
		component.addEventListener("onEcho", new EventListener<Event>() {

			public void onEvent(Event event) throws Exception {
				Thread.sleep(5000);
				Clients.clearBusy();
				component.removeEventListener("onEcho", this);
			}
		});
		Clients.showBusy("process long operation...");
		Events.echoEvent("onEcho", component, null);
	}
}

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-05-18 13:56:21 +0800

Seen: 555 times

Last updated: Oct 03 '12

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