grails select is not rendering value - grails

I want to make a select box in grails. I am using 2.1.0. I have a view page which shows a select box named class. But it does not shows any value. The list I have used in the from attribute of select works fine is browser when I render it as json. Can anyone make my combo box work for me please ? Here is my code below :
my view page >>>
<g:form controller="admistratorAction" action="addStudent">
<table class="centerTable">
<div class="height"></div>
<tr>
<td><label>Full Name :</label></td>
<td><g:textField name="fullname" id="fullname" class="field"/></td>
</tr>
<tr>
<td> <label>Admission Class :</label></td>
<td><g:select name="class" id="class" class="field" from="${classList}" noSelection="['':'-Choose a class-']"/></td>
</tr>
<td colspan="2" align="right"><g:submitButton name="createSubmit" value="Create" class="button" onclick="return confirm('Are you sure???')"/></td>
</tr>
</table>
</g:form>
here is my controller >>
package administrator
import common.classes.Classes
import grails.converters.JSON
class AdmistratorActionController {
def addStudent = {
render "add student"
}
def classList = {
def classes = Classes.executeQuery("SELECT c.classes FROM Classes c")
def all_class = [classes : classes]
render all_class as JSON
}
}

You do not need to convert it to JSON in order to have it in gsp page
class AdmistratorActionController {
def addStudent = {
def n = params.fullName
def c = params.class
// do something with them
}
def classList = {
def classes = Classes.list()
// pass details to view 'classList'
[classList : classes]
}
}
Create -> views/administratorAction/classList.gsp
have you form ready and you will be able to get ${classList} in it

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>

Grails, how can I pass list of object from gsp to controller

I have a list of csv files that will be imported in database.
So, in the first step, I display the name of files in the jsp page and then I wait the choice of user what's the file need to import it or to ignore it.
when the user confirms his response, I need to pass the list of files that user has chosen to import it to controller.
I thought about that : I set the list that contains a list of file in hidden field and i will recuperate it into controller action from form submit. But in the controller, it is read like a string variable and I can not extract data from it.
<g:hiddenField id="list_file_notimported" name="list_file_notimported" value="${list_file_notimported}" />
<table>
<g:findAll in="${list_file_notimported}" expr="1" >
<tr>
<td></td>
<td>${it.code}</td>
<td>${it.name}</td>
<td><g:radio id="group_${it.id}" name="group_${it.id}" value="import" checked="${false}" /></td>
<td><g:radio id="group_${it.id}" name="group_${it.id}" value="ignore" checked="${false}" /></td>
</tr>
</g:findAll></table>
Any idea please?
Thanks.
This example works in Grails 2.4.3:
In the controller, define index action to return a model and selection action to compute the list of files selected in the gsp:
class FileListController {
def index() {
[ list_file_notimported : [ 'a.csv', 'b.csv', 'c.csv', 'd.csv'] ]
}
def selection() {
def selectedfiles = []
params.keySet().each { String key ->
if (key.startsWith("group_") && key.endsWith(".csv") && params[key] == "import") {
selectedfiles << key.substring(6)
}
}
render(selectedfiles)
}
}
And in the view, create a form for the selection:
<g:form action="selection" method="get">
<table>
<tr><th>Name</th><th>Import</th><th>Ignore</th></tr>
<g:each var="it" in="${list_file_notimported}" >
<tr>
<td>${it}</td>
<td><g:radio name="group_${it}" value="import"/></td>
<td><g:radio name="group_${it}" value="ignore" checked="true"/></td>
</tr>
</g:each>
</table>
<g:actionSubmit value="selection"/>
</g:form>

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])
}

Multiple multipartfile upload testing in grails

I'm trying to write a test for file uploading in grails. I'm using spock as my testing framework.
I have a javascript function that link to a button on my view that adds an <input type="file"> to my form whenever it is clicked.
It looks something like this:
<script>
var fileNum = 1;
function addUploader() {
fileNum++;
var fileInputTag = "<input type=\"file\" name=\"myfile." +fileNum+ "\"/>";
var uploadField = document.getElementById("uploadFields");
var row = uploadField.insertRow(fileNum + 1);
var cell = row.insertCell(0);
cell.innerHTML = fileInputTag + "<br/>";
}
</script>
<tr>
<td>
<input type="file" class="required" name="myfile.1" />
</td>
</tr>
<tr>
<td> </td>
</tr>
<tr>
<td>
More Files <br />
<br/>
<input type="submit" value="Download"/>
</td>
</tr>
My controller looks something like this:
def uploadFile(){
List<MultipartFile> files = []
params.myfile.each {
if (it.value.isEmpty()) {
flash.message = message(code: 'upload.empty.message')
redirect(uri: "/")
return
}
files.add((MultipartFile) it.value)
}
def faxPreviews = []
faxPreviews = uploadFileService.generateFaxPreviews(files)
render(view:'/uploadfile/index', model:[p:uploadFileService.decodeFaxPreviews(faxPreviews)])
}
I want to test that a flash message is shown if the list is empty but I don't know how to put that in the test. I've been trying to search how to mock the view params in the test but so far no go.
This was actually very easy. D'oh! I ended up with this test.
void "updloadFile should warn when no files are attached."() {
given:
def file = new GrailsMockMultipartFile('mockFile', ''.bytes)
Map<MultipartFile> files = [:]
files[1] = file
controller.params.myfile = files
when:
controller.uploadFile()
then:
response.redirectedUrl == '/'
flash.message != null
}
My problem was that I thought the myfile in the view was a key when it is actually the name of a map. So myfile.1 would turn into a myfile[1] = "whatever value is passed to input"

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

Resources