Open woodmawa opened 12 years ago
You should use mvvm way to implement it,please refer:
didnt really answer the question i'm having a diffiuclty with
i'm using a template to render the rows in the grid. i'm trying to setup the first column as a <a href link that would trigger the edit form - provided elsewhere
i'm trying to build that link dynamically using grails g:createLink and need to pass the id: param of current record to the link.
as there is a var="book" set on the template i'd have expected to be able to use that reference in the grails tag but it erros
<z:template name="model" var ="book" >
<row >
<a label="@load (book.id)" href="${g.createLink(controller:'bookMVVM', action:'editMVVM', id:'book.id')}" />
<label value="@load (book.ISBN)" />
<label value="@load (book.title)" />
<label value="@load (book.dateCreated)" />
</row>
</z:template>
your crud page by MVVM doesnt address the discussion pointm which is how do i create the <a tag dynamically and pass that id across?
if i take the quotes of the 'book.id' and use id:book id - it all fails with null pointer exception
so
with no quotes this time - which id hoped would work and pass the id - fails with npe
Will
hi - i think im not not getting this and i have a problem
the CRUD example you pointed to doesnt help on a number of fronts - heres why and where i am stuck
i've been trying to reuse a grails controller as controller and as a view model at same time - and this causes issues when i do a redirect from @command action routine back to a std controller action (see issue 55 )
so i've split the grails controller from the View model this time, and put the view model in the grailsApp/vms directory - where you intend them to go . But there are issues now - the grailsApp/vms directory is ordinary groovy directory - so it has no access to g.methods, or redirect etc - as these are added by grails to controllers.
So whats the consequence of that - in the view model you cant ask the binder to get the View todo a redirect (at least i cant see how to do that)
the CRUD example you link to avoids the issue - it keeps all the view and view model in one place - with the list, edit, and create actions concident in the same view at the same time (single view never leaving that page)
so in my example i try to get a button with onClick="@command ('edit')" from a create.gsp to call the view model - that works and saves my record. However the view model isnt a controller - so it cant redirect, and can only return to the view.
if it returns to the create.gsp view - i cant see how to get the view to to a redirect by the grails controller to another action automatically
heres snippit from the view model
@Command ("create") // triggered by binder
def createNewInstance () {
println "create new instance called on ${this}, with new book " + selectedBook //+ " and passed " + newBook
def bookInstance = selectedBook //binder writes attributes into selectedBook
if (!bookInstance.save(flush: true) && bookInstance.hasErrors()) {
log.error bookInstance.errors
//self.renderErrors(bean: bookInstance) how to do this in view?
} else {
println "created book ${bookInstance}"
log.error "created book ${bookInstance}"
//flash.message = g.message(code: 'default.created.message', args: [g.message(code: 'book.label', default: 'Book'), bookInstance.id])
//flash.message = "book created id: " + bookInstance.id
//redirect(controller: "BookMVVM2", action: "listMVVM")
}
}
notice you cant use flash or redirect etc as its enhanced by grails to get these methods
here is my create gsp view
<z:window style="padding:5px" apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init ('com.softwood.BookMVVM2ViewModel')" >
<z:grid>
<z:columns sizable="true">
<z:column label="${message(code:'name',default:'Name')}" width="100px"/>
<z:column label="${message(code:'value',default:'Value')}"/>
</z:columns>
<z:rows>
<z:row>
<z:label value="${message(code:'book.ISBN.label',default:'ISBN')}"/>
<z:textbox name="ISBN" value="@bind (vm.selectedBook.ISBN)" />
</z:row>
<z:row>
<z:label value="${message(code:'book.title.label',default:'Title')}"/>
<z:textbox name="title" value="@bind (vm.selectedBook.title)" />
</z:row>
</z:rows>
</z:grid>
<z:hlayout>
<z:button id="saveButton" label="${message(code: 'default.button.create.label', default: 'Create')}"
onClick="@command('create')" href="${g.createLink(action:'listMVVM')}"/>
<z:button href="${g.createLink(action:'listMVVM')}" label="${message(code: 'default.list.label', args:[entityName])}"/>
</z:hlayout>
</z:window>
</body>
</html>
what i'd like to do is be able to get the view to redirect to another gsp - aka the list.gsp (i've even added href button to try and get it to go) that doesnt work
if a manually clik the second button - that does do a redirect and the list.gsp gets opened.
in this mode - my original issue which was that i couldnt pass an 'id:.id' into the g.createLink action cant be done anyhow as the View Model is just straight pojo with no grails controllers meta methods added .
so how to you drive the view from view model when you wan the view to move to next page ?
I hope my problem is clear to you - other than go back to MVC mode i'm not sure how get this to work under MVVM
In VM use org.zkoss.zk.ui.Executions for redirect
Executions.getCurrent().sendRedirect("/demo/index")
Hi woodmawa,
This is what I did to solve the issue you had. First of all ,Executions.current.sendRedirect('/demo/edit/5') doesn't fit my need. Why? Because to pass params to the Composer, I need to use an ugly format: /demo/edit/id=5 I don't want that, I want to use clean URLs. To make this work, I have to use the normal grails controllers.
For example, if I have a controller Country, with the default actions, and I want to redirect a user to a page to edit a country they select from a list that is using MVVM, I do the following in my VM:
@NotifyChange public void setSelected(selectedCountry){ Executions.current.sendRedirect("/country/edit/${selectedCountry.id}") }
And in my CountryController:
def edit(){ Country instance = Country.get(params.id.toLong()) render(view: "edit", model: [countryInstance: instance]) }
You could also pass binding parameters e.g.
<button label="Edit" onClick="@command('edit', id=each.id)" />
@Command
public void edit(@BindingParam("id") Integer id) {
Executions.current.sendRedirect("/contact/edit/${id}")
}
and do the Executions redirect in the wired edit method.
Here's more about the binding parameters http://books.zkoss.org/wiki/ZK%20Developer%27s%20Reference/MVVM/Advance/Parameters#A_Local_Command_Example
Nearly there but i cant figure out how to this - i've had a go at converting your generated MVC (composer ) output into hand cranked MVVM equiv to make sure i can get it all to hang together
i've recoded the list view - which works ok except for the link in the grid
i use <z:template to render first column as objects id but as a link -
but its that <a tag thats the difculty -
i want to format the link using grails createLink and set the id in the params map
but you say id:book.id - it says thats null, and your cant use id:@load (book.id) as throws parse errors on the page
how take that id in the template and call the grails createLink?