Grails passing params in controllers to selectBox - grails

Hey. I have this controller:
def participated_favourite = {
def user = User.get(1)
def conferenceUser
def original = ConferenceUser.findAllByUser(user)
def temp = ConferenceUser.findAllByUserAndIsFavourite(user, 1) // all conferenceUser filtered by User
def priz = [:]
def subm = [:]
...
...
[temp: temp, priz: priz, subm: subm, orig: original]
}
I want now to be able to select in a selectBox, the list of conferences passed by 'original' (in the participated_favourite.gsp).
How can i do that?
<g:select name="" from="${orig.list()}" optionKey="id" value="" />
This is giving me an empty select box which shouldnt. because there is one record in my database. What am i doing wrong?
Thanks in advances,
EDIT______________
I have in same gsp the folowing:
<g:each var="it" in="${orig}">
<table cellspacing="2">
<tbody><tr>
<th>Name</th>
</tr>
<tr>
<td class="color1">${it.conference}
</td>
</tr>
</tbody>
</table>
</g:each>
And it is p+rinting the values. So i dont know what is the problem in the select..

Try giving the name attribute a value.
---EDIT -----
Try the following to troubleshoot:
Does this work?
<g:select from="${ConferenceUser.list()}" />
If so, how about this?
<g:select from="${ConferenceUser.list()}" optionKey="id" />

use
<g:select name="" from="${orig}" optionKey="id" value="" />

Related

grails : how to pass params in remoteFunction

I want to a param using remoteFunction of grails.
HTML
<table class="table table-hover table-bordered" id="profittable">
<thead>
<tr>
<th>Date</th>
<th>Profit</th>
<th>Delete?</th>
</tr>
</thead>
<tbody>
<g:each in="${dailyProfit}" var="dp">
<tr onclick="<g:remoteFunction action='edit' params="[date:${dp.date}]"></g:remoteFunction>" >
<td><g:formatDate format="yyyy-MM-dd" date="${dp.date}"/></td>
<td>
<g:formatNumber number="${dp.profit}" type="currency" currencyCode="PHP" format="###.##" />
</td>
<td>
<g:form controller="dailyProfit" action="delete" >
<g:hiddenField name="date" value="${dp.date.format("yyyy-MM-dd")}" />
<g:actionSubmit class="delete" value="Delete" >
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
</g:actionSubmit>
</g:form>
</td>
</tr>
</g:each>
</tbody>
</table>
ERROR MESSAGE
URI /SampleGrailsApp/dailyProfit/index Class
org.codehaus.groovy.grails.web.taglib.exceptions.GrailsTagException
Message Attribute value quote wasn't closed (action='edit'
params="[date:${dp.date}]").
ACTIONS FOR EDIT
The remoteFunction tag is inside every tr of my table. The plan is, if the row is clicked, the edit page will appear
def edit() {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
Date date = format.parse(params.date);
def dailyProfit = DailyProfit.findByDate(date)
render view:"edit" , model:[dailyProfit : dailyProfit]
}
def update() {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
Date date = format.parse(params.date);
def dailyProfit = DailyProfit.findByDate(date)
if(dailyProfit){
dailyProfit.properties = params
dailyProfit.save(flush:true)
}
list()
}
What is the proper way of passing parameters using remoteFunction tag of grails?
You can do like this .
<tr onclick = "${remoteFunction(
controller: 'xyz',
action: 'edit',update:'divId',
params: [date: dp.date])}" >
This is also a valid syntax:
<tr onClick="<g:remoteFunction action='edit' params="${[param1: 'value', param2: 0]}"></g:remoteFunction>">.....</tr>
Note that the code will translate into an Ajax call with the parameters you indicate. Being an Ajax call, you wont see the page change.
If you want to send the user to the edit page when the row is clicked one option is the following:
<tr onclick='document.location = "<g:createLink action='edit' params="${[date: dp.date]}"/>" '> ... </tr>

How to keep query results after deleting an item?

In my Grails application I have multiple pages that list a group of data objects inside of a table. In these pages I provide a search function which when performed will adjust the table to only display the data objects that match the query. However If a user decides to delete one of these data objects the application will take them back to the default table which displays everything. I would like for query results to remain intact after performing a delete.
I will use my "Skill Evaluations" page as my example in this post.
Here is the relevant code in the domain class
SkillEval.groovy
class SkillEval {
static hasMany = [lines: SkillEvalL, courses: CourseOffering, choiceLabels: ChoiceLabel]
String name
String formVersion
static def search(params) {
def criteria = SkillEval.createCriteria()
def results = criteria.list(params) {
or {
ilike("name", params.search+'%')
}
}
return results
}
}
Relevant section of the gsp view file
list.gsp
<g:form>
<div class="search">
<label for="searchField">Search:</label> <input type="text"
id="searchField" name="search" value="${params.search}" /> <input
type="submit" value="Search" />
</div>
<br>
<table id="mainTable">
<thead>
<tr>
<th>Name</th>
<th>Version</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<g:each var="eval" in="${skillEvalList}">
<tr>
<td>
<strong>
${eval.name}
</strong>
</td>
<td>
${eval.formVersion}
</td>
<td>
<g:actionSubmit value="Delete" controller="skillEval" action="delete" onclick="setId(${eval.id});return confirm('Are you sure?');" class="delete" />
</td>
</tr>
</g:each>
</tbody>
</table>
<g:if test="${(skillEvalCount/maxCount) > 1}">
<div class="pagination">
<g:paginate action="list" total="${skillEvalCount}" />
</div>
</g:if>
<input id="evalId" type="hidden" name="id" value="" />
</g:form>
</div>
<r:script>
function setId(id)
{
$('#evalId').val(id);
}
</r:script>
Relevant code in the Controller class
SkillEvalController.groovy
def delete(Long id) {
def skillEval = SkillEval.get(id)
if (skillEval) {
def allInstances = SkillEvalI.findAllByForm(skillEval)
allInstances.each { evalInstance ->
evalInstance.lines.clear()
if(!evalInstance.delete()) {
println "Failed to delete skill eval instance"
}
else {
println "Instance successfully deleted."
}
}
try {
skillEval.delete(flush: true)
}
catch (DataIntegrityViolationException e) {
}
}
redirect(action: "list")
}
How can I make the view retain the queried results after deleting one of the queried items?
When you redirect to the list action you can provide parameters -- just capture the parameters (if any) in the delete action and pass them in the redirect call to list at the end of the controller action.
(Update: Forgot that actionSubmit does not accept params as an attribute, so cobbled together this solution from this SO answer and the Grails docs)
Example:
// View (list.gsp)
<g:actionSubmit action="deleteWithParams" value="Delete" ... />
// Controller
def list() {
def deleteWithParams = { forward(action:'delete', params:[search: params?.search]) }
render...
}
def delete(Long id) {
// Deleting the skillEval ...
redirect(action: "list", params: [search: params?.search])
}

Grails - Simple hasMany Problem - Using CheckBoxes rather than HTML Select in create.gsp

My problem is this: I want to create a grails domain instance, defining the 'Many' instances of another domain that it has. I have the actual source in a Google Code Project but the following should illustrate the problem.
class Person {
String name
static hasMany[skills:Skill]
static constraints = {
id (visible:false)
skills (nullable:false, blank:false)
}
}
class Skill {
String name
String description
static constraints = {
id (visible:false)
name (nullable:false, blank:false)
description (nullable:false, blank:false)
}
}
If you use this model and def scaffold for the two Controllers then you end up with a form like this that doesn't work;
My own attempt to get this to work enumerates the Skills as checkboxes and looks like this;
But when I save the Volunteer the skills are null!
This is the code for my save method;
def save = {
log.info "Saving: " + params.toString()
def skills = params.skills
log.info "Skills: " + skills
def volunteerInstance = new Volunteer(params)
log.info volunteerInstance
if (volunteerInstance.save(flush: true)) {
flash.message = "${message(code: 'default.created.message', args: [message(code: 'volunteer.label', default: 'Volunteer'), volunteerInstance.id])}"
redirect(action: "show", id: volunteerInstance.id)
log.info volunteerInstance
}
else {
render(view: "create", model: [volunteerInstance: volunteerInstance])
}
}
This is my log output (I have custom toString() methods);
2010-05-10 21:06:41,494 [http-8080-3] INFO bumbumtrain.VolunteerController - Saving: ["skills":["1", "2"], "name":"Ian", "_skills":["", ""], "create":"Create", "action":"save", "controller":"volunteer"]
2010-05-10 21:06:41,495 [http-8080-3] INFO bumbumtrain.VolunteerController - Skills: [1, 2]
2010-05-10 21:06:41,508 [http-8080-3] INFO bumbumtrain.VolunteerController - Volunteer[ id: null | Name: Ian | Skills [Skill[ id: 1 | Name: Carpenter ] , Skill[ id: 2 | Name: Sound Engineer ] ]]
Note that in the final log line the right Skills have been picked up and are part of the object instance. When the volunteer is saved the 'Skills' are ignored and not commited to the database despite the in memory version created clearly does have the items. Is it not possible to pass the Skills at construction time? There must be a way round this? I need a single form to allow a person to register but I want to normalise the data so that I can add more skills at a later time.
If you think this should 'just work' then a link to a working example would be great.
If I use the HTML Select then it works fine! Such as the following to make the Create page;
<tr class="prop">
<td valign="top" class="name">
<label for="skills"><g:message code="volunteer.skills.label" default="Skills" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: volunteerInstance, field: 'skills', 'errors')}">
<g:select name="skills" from="${uk.co.bumbumtrain.Skill.list()}" multiple="yes" optionKey="id" size="5" value="${volunteerInstance?.skills}" />
</td>
</tr>
But I need it to work with checkboxes like this;
<tr class="prop">
<td valign="top" class="name">
<label for="skills"><g:message code="volunteer.skills.label" default="Skills" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: volunteerInstance, field: 'skills', 'errors')}">
<g:each in="${skillInstanceList}" status="i" var="skillInstance">
<label for="${skillInstance?.name}"><g:message code="${skillInstance?.name}.label" default="${skillInstance?.name}" /></label>
<g:checkBox name="skills" value="${skillInstance?.id.toString()}"/>
</g:each>
</td>
</tr>
The log output is exactly the same! With both style of form the Volunteer instance is created with the Skills correctly referenced in the 'Skills' variable. When saving, the latter fails with a null reference exception as shown at the top of this question.
Hope this makes sense, thanks in advance!
Gav
Replace your create.gsp <g:checkbox...> code by:
<g:checkBox name="skill_${skillInstance.id}"/>
Then inside the save action of your controller, replace def volunteerInstance = new Volunteer(params) by :
def volunteerInstance = new Volunteer(name: params.name)
params.each {
if (it.key.startsWith("skill_"))
volunteerInstance.skills << Skill.get((it.key - "skill_") as Integer)
}
Should work. (code not tested)
I would reader send id list of your has many elements because this can be easily assigned by default in Grails.
Your .gsp should look like:
<g:each in="${skills}" var="skill">
<input type="checkbox"
name="skills"
value="${skill?.id}"
</g:each>
and in your controller you can simply stores the value like this:
person.properties = params
person.validate()
person.save()
It's pretty easy, isn't it? :-)
Grails does not provide data-binding support when you use a checkbox and you want to bind ToMany associations. At least, up to version 2.2.0
Workaround ?
1º option - Write gsp code which behaves like a select component
<g:each var="skillInstance" in="${skillInstanceList}">
<div class="fieldcontain">
<g:set var="checked" value=""/>
<g:if test="${volunteerInstance?.skills?.contains(skillInstance)}">
<input type="hidden" name="_skills" value="${skillInstance?.id}"/>
<g:set var="checked" value="checked"/>
</g:if>
<label for="${skillInstance?.name}">
<g:message code="${skillInstance?.name}.label"
default="${skillInstance?.name}" />
</label>
<input type="checkbox" name="skills" value="${skillInstance?.id}"
${checked} />
</div>
</g:each>
2º Create your own TagLib
/**
* Custom TagLib must end up with the TagLib suffix
*
* It should be placed in the grails-app/taglib directory
*/
class BindingAwareCheckboxTagLib {
def bindingAwareCheckbox = { attrs, body ->
out << render(
template: "/<TEMPLATE_DIR>/bindingAwareCheckboxTemplate.gsp",
model: [referenceColletion: attrs.referenceColletion,
value:attrs.value])
}
}
Where <TEMPLATE_DIR> should be relative to the /grails-app/views directory. Furthermore, templates should be prefixed with _.
Now you can use your custom TagLib as follows
<g:bindingAwareCheckbox
referenceCollection="${skillInstanceList}"
value="${volunteerInstance?.skills}"/>
Once done, binding process will occur automatically. No additional code needed.
GSP
<g:checkBox name="skills" value="${skillInstance.id}" checked="${skillInstance in volunteerInstance?.skills}"/>
Groovy
def volunteerInstance = new Volunteer(params).save()
def skills = Skill.getAll(params.list('skills'))
skills.each{ volunteerInstance.addToSkills(it).save() }

grails default values

I have an application written in grails.
I want to add a new domain class with default initial values.
These values should appear as default or initial values
under the create view.
I mean, the generated inout field tag should have this value as
an attribute.
The class (simplified) look as follows:
class Whatever{
static constraints = {
myString(blank:false, nullable:false)
}
String myString = "hallo"
The generated view looks as follows:
...
<td valign="top" class="value ${hasErrors(bean: whatEverInstance, field: 'myString', 'errors')}">
<g:textField name="serviceReview" value="${fieldValue(bean: whatEverInstance, field: 'myString')}" />
</td>
For some unknown reason when the source of render page has looks as follows:
<td valign="top" class="value ">
<input type="text" name="myString" value="" id="myString" />
</td>
I was expecting value="hallo".
I mean:
<td valign="top" class="value ">
<input type="text" name="myString" value="hallo" id="myString" />
</td>
What am I doing wrong?
Thanks in advance,
Luis
EDIT:
My create method is as follows:
def create = {
def whateverInstance = new Whatever()
whateverInstance.properties = params
return [whateverInstance: whateverInstance]
}
But the create method is called after the form is filled.
int varm
static mapping = {
table 'Test55'
id column: "kid", name:"kid"
version false
varm column: 'varm', name: 'varm', sqlType: 'numeric(1) default 1'
}
This works
Is you whatEverInstance bean being set in the controller's create setup action?
def create = {
[whateverInstance: new Whatever()]
}
You could test the value of whateverInstance in the gsp with:
${whateverInstance}

Passing data from GSP to a controller in Grails

I create a GSP page with controls depending on the rows in a database.
This depends on the value returned by the <g:each in="${Vehicles}" var="vehicle">
So, if there are 3 vehicles, 3 rows with text boxes will be generated. (The maximum can be 200)
<g:form action="update" >
<label for="SearchTerm">${term}</label>
<g:each in="${Vehicles}" var="vehicle">
<tr>
<td> <label for="Name">${vehicle.name}</label> </td>
<td><g:textField name="${vehicle.id}.ModelNo" /> </td>
<td><g:textField name="${vehicle.id}.Year" /> </td>
</tr>
</g:each>
<td> <g:submitButton name="update" value="Update"/></td>
</g:form>
How can I basically pass this value to my controller so that I can then save/update the data to the database. or Is there any easy way to achieve this scenario?
You need some code like this in the GSP
<g:form action="update" >
<label for="SearchTerm">${term}</label>
<g:each in="${Vehicles}" var="vehicle" status="i">
<tr>
<td> <label for="Name">${vehicle.name}</label> </td>
<td><g:hiddenField name="vehicle[${i}].id" value="${vehicle.id}"/>
<g:textField name="vehicle[${i}].ModelNo" value="${vehicle.ModelNo}"/> </td>
<td><g:textField name="vehicle[${i}].Year" value="${vehicle.Year}"/> </td>
</tr>
</g:each>
<td> <g:submitButton name="update" value="Update"/></td>
</g:form>
The Controller needs to either have a Domain with a List Property or a Command Object with a List Property ie
SearchCommand {
List<Vehicle> vehicle = new Arraylist<Vehicle>(3);
}
Then in the controller (if using the command object)
def save = {SearchCommand searchCmd->
searchCmd.vehicle.each {vehicle ->
/* Process Vehicle */
}
}
Hope that Helps
You need to use the request object from your controller. If you can generate the names of the controls you need to access do something like the following
idList.each {
theYear=request.getParameter(it+Year)
}
If you want a list of all your generated form fields use something like
java.util.Enumeration theFields=request.getParameterNames()
theFields.each {
//look at your field name and take appropriate action
}
For more info on the request object see this

Resources