The 6.0 release of ZK introduced the MVVM pattern and they have been fairly well documented in their website. Using the new pattern with zkgrails is another story. Its major attraction to me is that it is farily easy to unit test a ViewModel, compared to testing a Composer(has anyone been able to do this?). I decided delved into it today and figured that the best way to do it was to start a brand new project and try different things. In the end, I did the hard way first and later found out a rather easier way. So, without further ado, here we go.
The source code for the sample app can be found on github. I won't explain how to install grails and the zkgrails plugin. The domain class Person is shown here: First I needed a form to create persons, so I created the corresponding zul: create-zul com.example.create This creates a zul under grails-app/zul The corresponding view model was also created: create-viewmodel com.example.Person A PersonViewModel.groovy was added to grails-app/viewmodels/com/example/ ZK has some issues keeping hibernate sessions, so as a work around, zkgrails has facades. We will use a PersonFacade to interact with GORM: The test for the PersonViewModel: And finally our PersonViewModel: A couple things to point out before we continue.- @WireVariable is needed to wire a spring bean. All facades created by zkgrails are spring beans, so we need this annotation to wire it.
- @NotifyChange is used to notify the corresponding variables of any changes.
- @Command is the equivalent of an onCLick_ method. This can be used to bind an event in the UI to a method in the ViewModel.
- A custom validtor to ensure that the first name is added.
- @id('vm') : this assigns viewmodel to a variable(vm) allowing us to access it throughout our view.
- @init('com.example.PersonViewModel') : assigns an instance of this class to vm.
- validationMessages="@id('vmsgs')" : all validation messages from our custom validators can be accessed with this variable(vmsgs).
<label value="@load(vmsgs[firstNameTextbox])" style="color:red;"/>
Finally, we have to tell the form what to do when its submitted. This is done by assigning a 'command' to a button:
<button id="createButton" label="Create" onClick="@command('save'))" />
create-zul-viewmodel
This will create a zul and a corresponding view model wired together, without the need to have the composer extend BindComposer: That's it. The surface of MVVM in zkgrails.
Thanks, I appreciate your effort, it helped get me going quickly!
ReplyDeleteMark
You're welcome. I try to cover a little more details in my other blog: http://stumblingoncode.wordpress.com
Deletehi, i've downloaded your sample app from github,
ReplyDeletewhen i open list.zul, i encountered this error :
"cannot convert [] of type class java.util.ArrayList to interface org.zkoss.zul.ListModel"
did i miss something?
btw, i'm using grails 2.1 and zk-2.0.4
This was created with a pretty old version. I know there have been lots of fixes seen then. What I think is happening is that persons in ListViewModel needs to be of type org.zkoss.zul.ListModel. ListModel is an interface, so you will need to use org.zkoss.zul.ListModelList.
DeleteThis is what I did to have this issue resolved. Just in case someone else runs into this problem:
ReplyDelete1. Specify the type of the ViewModel to Set. e.g. "def persons" to "Set persons"
2. run-app. (The problem seemed to go away already at this point, and I have only changed one of the VMs)
3. Change the type "Set persons" back to "def persons" and the application seemed to stay intact.
Hi, thanks for sharing that! I'm still a little bit confused about the zul. You applied a Composer and a ModelView to the view, is that correct? They work together?
ReplyDeleteYes, both composer and ModelViews are applied to the zul. The composer is a 'controller' and the ModelView is that model(data) that is passed to the view to display.
ReplyDelete