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

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 retag edit

## 10 Replies

Matze2
773 7

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.

rickcr
704 7

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?

Matze2
773 7

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.

rickcr
704 7

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()"

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.

rickcr
704 7

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?

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

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/

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

samchuang
4084 4

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) {

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


[hide preview]