Passing parameters to a form grails - grails

I am new to grails I am trying to pass an object Id to a form. I have domains called Beer and recipe. Beer hasMany recipes and recipe belongsTo beer. I want to create a link to a new recipe from the beer show page passing the beer id in the url in order to create the association. Right now I have been trying to use this link <g:link controller="recpie" action="create" params="[beerid: selectedBeer.id]">Create Recipe</g:link> and retrieve it in the form as a hidden field to submit with the recipe form using <g:field type="text" name="beer.id" value="${beer}"/>.(I know that the hidden property is not set). What am I doing wrong? Also is there a better way to create this association?
Beer Domain Class
class Beer {
String name
String style
Recipe recipe
String toString() {
name
}
static hasMany = [recipe : Recipe]
static constraints = {
}
}
Recipe Domain Class
class Recipe {
String name
Float grainAmount
String yeast
float boilTime
Float hopAmount
float og
float fg
float ogTemp
float fgTemp
float fermTime
Beer beer
static belongsTo = [ beer: Beer]
static constraints = {
beer nullable: true
}
String toString() {
name
}
}
Beer Controller
package com.example
import static org.springframework.http.HttpStatus.*
import grails.transaction.Transactional
#Transactional(readOnly = true)
class BeerController {
static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
respond Beer.list(params), model:[beerCount: Beer.count()]
}
def show(Beer beer) {
respond beer
}
def create() {
respond new Beer(params)
}
#Transactional
def save(Beer beer) {
if (beer == null) {
transactionStatus.setRollbackOnly()
notFound()
return
}
if (beer.hasErrors()) {
transactionStatus.setRollbackOnly()
respond beer.errors, view:'create'
return
}
beer.save flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message', args: [message(code: 'beer.label', default: 'Beer'), beer.id])
redirect beer
}
'*' { respond beer, [status: CREATED] }
}
}
def edit(Beer beer) {
respond beer
}
#Transactional
def update(Beer beer) {
if (beer == null) {
transactionStatus.setRollbackOnly()
notFound()
return
}
if (beer.hasErrors()) {
transactionStatus.setRollbackOnly()
respond beer.errors, view:'edit'
return
}
beer.save flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.updated.message', args: [message(code: 'beer.label', default: 'Beer'), beer.id])
redirect beer
}
'*'{ respond beer, [status: OK] }
}
}
#Transactional
def delete(Beer beer) {
if (beer == null) {
transactionStatus.setRollbackOnly()
notFound()
return
}
beer.delete flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.deleted.message', args: [message(code: 'beer.label', default: 'Beer'), beer.id])
redirect action:"index", method:"GET"
}
'*'{ render status: NO_CONTENT }
}
}
protected void notFound() {
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'beer.label', default: 'Beer'), params.id])
redirect action: "index", method: "GET"
}
'*'{ render status: NOT_FOUND }
}
}
}
Recipe Controller
package com.example
import static org.springframework.http.HttpStatus.*
import grails.transaction.Transactional
#Transactional(readOnly = true)
class RecipeController {
static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
respond Recipe.list(params), model:[recipeCount: Recipe.count()]
}
def show(Recipe recipe) {
respond recipe
}
def create() {
respond new Recipe(params)
}
#Transactional
def save(Recipe recipe) {
if (recipe == null) {
transactionStatus.setRollbackOnly()
notFound()
return
}
if (recipe.hasErrors()) {
transactionStatus.setRollbackOnly()
respond recipe.errors, view:'create'
return
}
recipe.save flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message', args: [message(code: 'recipe.label', default: 'Recipe'), recipe.id])
redirect recipe
}
'*' { respond recipe, [status: CREATED] }
}
}
def edit(Recipe recipe) {
respond recipe
}
#Transactional
def update(Recipe recipe) {
if (recipe == null) {
transactionStatus.setRollbackOnly()
notFound()
return
}
if (recipe.hasErrors()) {
transactionStatus.setRollbackOnly()
respond recipe.errors, view:'edit'
return
}
recipe.save flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.updated.message', args: [message(code: 'recipe.label', default: 'Recipe'), recipe.id])
redirect recipe
}
'*'{ respond recipe, [status: OK] }
}
}
#Transactional
def delete(Recipe recipe) {
if (recipe == null) {
transactionStatus.setRollbackOnly()
notFound()
return
}
recipe.delete flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.deleted.message', args: [message(code: 'recipe.label', default: 'Recipe'), recipe.id])
redirect action:"index", method:"GET"
}
'*'{ render status: NO_CONTENT }
}
}
protected void notFound() {
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'recipe.label', default: 'Recipe'), params.id])
redirect action: "index", method: "GET"
}
'*'{ render status: NOT_FOUND }
}
}
}
Beer/Show GSP
<!DOCTYPE html>
<html>
<head>
<meta name="layout" content="main" />
<g:set var="entityName" value="${message(code: 'beer.label', default: 'Beer')}" />
<title><g:message code="default.show.label" args="[entityName]" /></title>
</head>
<body>
<g:message code="default.link.skip.label" default="Skip to content…"/>
<div class="nav" role="navigation">
<ul>
<li><a class="home" href="${createLink(uri: '/')}"><g:message code="default.home.label"/></a></li>
<li><g:link class="list" action="index"><g:message code="default.list.label" args="[entityName]" /></g:link></li>
<li><g:link class="list" action="create" resource="recipe">New Recipe</g:link></li>
</ul>
</div>
<div id="show-beer" class="content scaffold-show" role="main">
<h1><g:message code="default.show.label" args="[entityName]" /></h1>
<g:if test="${flash.message}">
<div class="message" role="status">${flash.message}</div>
</g:if>
<g:link controller="recpie" action="create" resource="recipe" params="[beerid: selectedBeer.id]">Create Recipe</g:link>
<f:display bean="beer" />
<g:form resource="${this.beer}" method="DELETE">
<fieldset class="buttons">
<g:link class="edit" action="edit" resource="${this.beer}"><g:message code="default.button.edit.label" default="Edit" /></g:link>
<input class="delete" type="submit" value="${message(code: 'default.button.delete.label', default: 'Delete')}" onclick="return confirm('${message(code: 'default.button.delete.confirm.message', default: 'Are you sure?')}');" />
</fieldset>
</g:form>
</div>
</body>
</html>
** Recipe/Create GSP**
<%# page import="com.example.Beer" %>
<!DOCTYPE html>
<html>
<head>
<meta name="layout" content="main" />
<g:set var="entityName" value="${message(code: 'recipe.label', default: 'Recipe')}" />
<title><g:message code="default.create.label" args="[entityName]" /></title>
</head>
<body>
<g:message code="default.link.skip.label" default="Skip to content…"/>
<div class="nav" role="navigation">
<ul>
<li><a class="home" href="${createLink(uri: '/')}"><g:message code="default.home.label"/></a></li>
<li><g:link class="list" action="index"><g:message code="default.list.label" args="[entityName]" /></g:link></li>
</ul>
</div>
<div id="create-recipe" class="content scaffold-create" role="main">
<h1><g:message code="default.create.label" args="[entityName]" /></h1>
<g:if test="${flash.message}">
<div class="message" role="status">${flash.message}</div>
</g:if>
<g:hasErrors bean="${this.recipe}">
<ul class="errors" role="alert">
<g:eachError bean="${this.recipe}" var="error">
<li <g:if test="${error in org.springframework.validation.FieldError}">data-field-id="${error.field}"</g:if>><g:message error="${error}"/></li>
</g:eachError>
</ul>
</g:hasErrors>
<g:form action="save" name="recipeForm">
<fieldset class="form">
Name:
<g:field type="text" name="name"/>
Grain Amount:
<g:field type="text" name="grainAmount"/>
Yeast:
<g:field type="text" name="yeast"/>
Boil Time:
<g:field type="text" name="boilTime"/>
Hop Amount:
<g:field type="text" name="hopAmount"/>
OG:
<g:field type="text" name="og"/>
FG:
<g:field type="text" name="fg"/>
OG Temp:
<g:field type="text" name="ogTemp"/>
FG Temp:
<g:field type="text" name="fgTemp"/>
Ferment Time:
<g:field type="text" name="fermTime"/>
beer:
<g:hiddenField name="beerid" value="${params.beerid}" />
</fieldset>
<fieldset class="buttons">
<g:submitButton name="create" class="save" value="${message(code: 'default.button.create.label', default: 'Create')}" />
</fieldset>
</g:form>
</div>
</body>
</html>

You've submitted the beer ID from the beer show paged named beerid so you need to retrieve it from the params on the recipe create page as such:
beer - show.gsp
<g:link controller="recipe" action="create" resource="recipe" params="[beerid: beer.id]">Create Recipe</g:link>
recpie - create.gsp
<g:hiddenField name="beer.id" value="${params.beerid}"/>

Related

No such property: propertyName for class: org.grails.orm.hibernate.cfg.HibernatePersistentEntity

im new to grails, and i want to style my f:table in the index.gsp, i created a file _table.gsp, when i execute i get this error :
No such property: propertyName for class: org.grails.orm.hibernate.cfg.HibernatePersistentEntity
index.gsp
<!DOCTYPE html>
<html>
<head>
<meta name="layout" content="main" />
<g:set var="entityName" value="${message(code: 'user.label', default: 'User')}" />
<title><g:message code="default.list.label" args="[entityName]" /></title>
</head>
<body>
<div class="breadcrumbs">
<div class="col-sm-3">
<g:message code="default.link.skip.label" default="Skip to content…"/>
</div>
<div class="col-sm-3">
<a class="home" href="${createLink(uri: '/')}"><g:message code="default.home.label"/></a>
</div>
<div class="col-sm-3">
<g:link class="create" action="create"><g:message code="default.new.label" args="[entityName]" /></g:link>
</div>
</div>
<br>
<br>
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-header">
<strong class="card-title"><g:message code="default.list.label" args="[entityName]" /></strong>
</div>
<div class="card-body">
<div id="pay-invoice">
<div class="card-body">
<div id="list-user" class="content scaffold-list" role="main">
<g:if test="${flash.message}">
<div class="message" role="status">${flash.message}</div>
</g:if>
<f:table collection="${userList}"/>
<div class="pagination">
<g:paginate total="${userCount ?: 0}" />
</div>
</div>
</div>
</div>
</div>
</div> <!-- .card -->
</div>
</div>
</body>
</html>
_table.gsp
<table class="table stripped-table">
<thead>
<tr>
<g:each in="${domainClass}" var="p" status="i">
<g:set var="propTitle">${domainClass.propertyName}.${p.name}.label</g:set>
<g:sortableColumn property="${p.name}" title="${message(code: propTitle, default: p.naturalName)}" />
</g:each>
</tr>
</thead>
<tbody>
<g:each in="${collection}" var="bean" status="i">
<tr class="${(i % 2) == 0 ? 'even' : 'odd'}">
<g:each in="${domainProperties}" var="p" status="j">
<g:if test="${j==0}">
<td><g:link method="GET" resource="${bean}"><f:display bean="${bean}" property="${p.name}" displayStyle="${displayStyle?:'table'}" /></g:link></td>
</g:if>
<g:else>
<td><f:display bean="${bean}" property="${p.name}" displayStyle="${displayStyle?:'table'}" /></td>
</g:else>
</g:each>
</tr>
</g:each>
</tbody>
</table>
User.groovy
class User {
transient securiteService
String username
String password
String nom
String prenom
String email
String tel
static hasMany = [roles : Role]
static constraints = {
username blank: false, unique: true
password blank: false
nom nullable: true
prenom nullable: true
email email:true, nullable:true
tel nullable:true, maxSize:20, matches:/[\+]{0,1}[0-9\s]{3,15}/
}
static mapping = {
password column: '`password`'
sort nom: "asc"
affectations sort : "dateAffectation", order:"desc"
intervention sort : "responsable", order:"desc"
}
}
usercontroller.groovy :
package mylicence
import grails.validation.ValidationException
import static org.springframework.http.HttpStatus.*
import java.security.MessageDigest
class UserController {
UserService userService
static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
respond userService.list(params), model:[userCount: userService.count()]
}
def show(Long id) {
respond userService.get(id)
}
def create() {
respond new User(username: params.username, password: params.password, nom: params.nom, prenom: params.prenom, email: params.email, tel: params.tel)
}
def save(User user) {
if (user == null) {
notFound()
return
}
try {
userService.save(user)
} catch (ValidationException e) {
respond user.errors, view:'create'
return
}
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message', args: [message(code: 'user.label', default: 'User'), user.id])
redirect user
}
'*' { respond user, [status: CREATED] }
}
}
def edit(Long id) {
respond userService.get(id)
}
def update(User user) {
if (user == null) {
notFound()
return
}
try {
userService.save(user)
} catch (ValidationException e) {
respond user.errors, view:'edit'
return
}
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.updated.message', args: [message(code: 'user.label', default: 'User'), user.id])
redirect user
}
'*'{ respond user, [status: OK] }
}
}
def delete(Long id) {
if (id == null) {
notFound()
return
}
userService.delete(id)
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.deleted.message', args: [message(code: 'user.label', default: 'User'), id])
redirect action:"index", method:"GET"
}
'*'{ render status: NO_CONTENT }
}
}
protected void notFound() {
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'user.label', default: 'User'), params.id])
redirect action: "index", method: "GET"
}
'*'{ render status: NOT_FOUND }
}
}
def login() {
}
def handlelogin = {
def hashPassd = params.password
// Find the username
def user = User.findByUsernameAndPassword(params.username, hashPassd)
if (!user) {
flash.message = "User not found for userName: ${params.username}"
redirect(action:'login')
return
} else {
session.user = user
redirect(controller:'user')
}
}
def logout = {
//log.info 'logout'
if(session.user) {
session.user = null
session.invalidate()
redirect(controller:'user', action: 'login')
}
else {
redirect(controller:'user', action: 'login')
}
}
}
i searched every where with no solution, im using grails 3.3.4, groovy 2.4.14, JVM 1.8.0_161
had the same problem here's my solution:
<%# page import="grails.util.GrailsNameUtils" %>
<table >
<thead>
<tr>
<g:each in="${domainProperties}" var="p" status="i">
<g:set var="propTitle">${domainClass.decapitalizedName}.${p.name}.label</g:set>
<g:sortableColumn property="${p.name}" title="${message(code: propTitle, default: grails.util.GrailsNameUtils.getNaturalName(p.name))}" />
</g:each>
</tr>
</thead>
<tbody>
<g:each in="${collection}" var="bean" status="i">
<tr class="${(i % 2) == 0 ? 'even' : 'odd'}">
<g:each in="${domainProperties}" var="p" status="j">
<g:if test="${j==0}">
<td><g:link method="GET" resource="${bean}"><f:display bean="${bean}" property="${p.name}" displayStyle="${displayStyle?:'table'}" /></g:link></td>
</g:if>
<g:else>
<td><f:display bean="${bean}" property="${p.name}" displayStyle="${displayStyle?:'table'}" /></td>
</g:else>
</g:each>
</tr>
</g:each>
</tbody>
</table>
I had to import the grails.util.GrailsNameUtils library to display the name in natural format.

dataTable Can't show more than 10 rows in table

I've encountered a problem while trying to list the users in the table using dataTable.
So far everything is working fine but when I enter more than 10 users, it still shows me 10 rows and can't view more than 10 rows. I've been trying to use the show by 10 25 50 100 entries but still can't work.
Here is the screen shot of the function that i've been trying to use:
This is the table that i use:
$(document).ready(function() {
$('table.dataTable').dataTable();
} );
This is my domain:
class Pilot {
String fName
String lName
static constraints = {
}
}
Here is the Controller:
class PilotController {
static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
def index() {
redirect(action: "list", params: params)
}
def list(Integer max) {
params.max = Math.min(max ?: 10, 100)
[pilotInstanceList: Pilot.list(params), pilotInstanceTotal: Pilot.count()]
}
def create() {
[pilotInstance: new Pilot(params)]
}
def save() {
def pilotInstance = new Pilot(params)
if (!pilotInstance.save(flush: true)) {
render(view: "create", model: [pilotInstance: pilotInstance])
return
}
flash.message = message(code: 'default.created.message', args: [message(code: 'pilot.label', default: 'Pilot'), pilotInstance.id])
redirect(action: "show", id: pilotInstance.id)
}
def show(Long id) {
def pilotInstance = Pilot.get(id)
if (!pilotInstance) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'pilot.label', default: 'Pilot'), id])
redirect(action: "list")
return
}
[pilotInstance: pilotInstance]
}
def edit(Long id) {
def pilotInstance = Pilot.get(id)
if (!pilotInstance) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'pilot.label', default: 'Pilot'), id])
redirect(action: "list")
return
}
[pilotInstance: pilotInstance]
}
def update(Long id, Long version) {
def pilotInstance = Pilot.get(id)
if (!pilotInstance) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'pilot.label', default: 'Pilot'), id])
redirect(action: "list")
return
}
if (version != null) {
if (pilotInstance.version > version) {
pilotInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
[message(code: 'pilot.label', default: 'Pilot')] as Object[],
"Another user has updated this Pilot while you were editing")
render(view: "edit", model: [pilotInstance: pilotInstance])
return
}
}
pilotInstance.properties = params
if (!pilotInstance.save(flush: true)) {
render(view: "edit", model: [pilotInstance: pilotInstance])
return
}
flash.message = message(code: 'default.updated.message', args: [message(code: 'pilot.label', default: 'Pilot'), pilotInstance.id])
redirect(action: "show", id: pilotInstance.id)
}
def delete(Long id) {
def pilotInstance = Pilot.get(id)
if (!pilotInstance) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'pilot.label', default: 'Pilot'), id])
redirect(action: "list")
return
}
try {
pilotInstance.delete(flush: true)
flash.message = message(code: 'default.deleted.message', args: [message(code: 'pilot.label', default: 'Pilot'), id])
redirect(action: "list")
}
catch (DataIntegrityViolationException e) {
flash.message = message(code: 'default.not.deleted.message', args: [message(code: 'pilot.label', default: 'Pilot'), id])
redirect(action: "show", id: id)
}
}
}
And here is the list View:
<!DOCTYPE html>
<html>
<head>
<meta name="layout" content="bstheme">
<g:set var="entityName" value="${message(code: 'pilot.label', default: 'Pilot')}" />
<title><g:message code="default.list.label" args="[entityName]" /></title>
</head>
<body>
<div class="col-md-12">
<div class="panel panel-custom">
<!--<g:message code="default.link.skip.label" default="Skip to content…"/>-->
<div class="panel-heading">
<g:message code="default.list.label" args="[entityName]" />
<div class="panel-options">
<a class="home" href="${createLink(uri: '/')}"><i class="glyphicon glyphicon-home"></i></a>
<g:link class="create" action="create"><i class="glyphicon glyphicon-plus"></i></g:link>
</div>
</div>
<div class="panel-body">
<div id="list-pilot" class="content scaffold-list" role="main">
<!--<h1><g:message code="default.list.label" args="[entityName]" /></h1>-->
<g:if test="${flash.message}">
<div class="message" role="status">${flash.message}</div>
</g:if>
<table class="dataTable table table-striped table-hover table-responsive">
<thead>
<tr>
<g:sortableColumn property="fName" title="${message(code: 'pilot.fName.label', default: 'First Name')}" />
<g:sortableColumn property="lName" title="${message(code: 'pilot.lName.label', default: 'Last Name')}" />
</tr>
</thead>
<tbody>
<g:each in="${pilotInstanceList}" status="i" var="pilotInstance">
<tr class="${(i % 2) == 0 ? 'even' : 'odd'}">
<td><g:link action="show" id="${pilotInstance.id}">${fieldValue(bean: pilotInstance, field: "fName")}</g:link></td>
<td>${fieldValue(bean: pilotInstance, field: "lName")}</td>
</tr>
</g:each>
</tbody>
</table>
<%-- <div class="pagination">
<g:paginate total="${pilotInstanceTotal}" />
</div> --%>
</div>
</div>
</div>
</div>
</body>
</html>
Found the solution to this problem,
def list(Integer max) {
params.max = Math.min(max ?: 10, 100)
[pilotInstanceList: Pilot.list(params), pilotInstanceTotal: Pilot.count()]
}
All you need to do is remove:
Math.min(max ?: 10, 100) in the controller,
So your code should look like this
def list(Integer max) {
params.max
[pilotInstanceList: Pilot.list(params), pilotInstanceTotal: Pilot.count()]
}
Hope this helps you in future if any of you are facing the same problem.
Kam rabwa
PilotController.list(..) returns 10 Entries if no max is given, but you don't set the max, anything else cannot happen.
And You commented pagination out, so there is no way to get the follwing entries.

g:select save to database selected item in grails

I have tables: Products and Shop.(I generate controllers using grails generate-all) Shop hasmany products
I'm trying to do is List all the shops in and save to database selected shop when creating a new product.
I listed all values using
<g:form controller="product" action="save" role="form">
<div class="form-horizontal" role="form">
<div class="form-group">
<label class="col-lg-3 control-label">Product Name:</label>
<div class="col-lg-8">
<g:textField name="productName" class="form-control" value="${product.productName}"/>
</div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">Product Barcode</label>
<div class="col-lg-8">
<g:textField name="date expired" class="form-control" value="${product.productBarcode}"></g:textField>
</div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">Product Shop</label>
<g:select class="selectpicker" name="products.id" from="${tr.com.netiket.lkkstoreapp.Shop.list()}" value="shop?.products.id" optionValue="shopName"></g:select>
</div>
</g:form>
when i click create button it says
Property [shop] of class [class tr.com.nur.storeapp.Product] cannot be null
This bit doesn't look right:
<g:select class="selectpicker" name="products.id" from="${tr.com.netiket.lkkstoreapp.Shop.list()}" value="shop?.products.id" optionValue="shopName"></g:select>
The name should be the id of the Shop and the value should be the product's shop id, if present:
<g:select class="selectpicker" name="shop.id" from="${tr.com.netiket.lkkstoreapp.Shop.list()}" value="${product?.shop?.id}" optionValue="shopName"></g:select>
#Transactional
def save(Shop shop) {
//println "in shop save"
def currentUser=(User)springSecurityService.currentUser
shop.user=currentUser
shop.validate()
if (!shop) {
//println "I have no shop"
transactionStatus.setRollbackOnly()
notFound()
return
}
//if (shop.hasErrors()) {
if (shop.save(flush:true)) {
//println "shop has errors"
transactionStatus.setRollbackOnly()
respond shop.errors, view:'create'
shop.errors.allErrors
return
}
//shop.save flush:true
//println "shop has saved"
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message', args: [message(code: 'shop.label', default: 'Shop'), shop.id])
//println "redirecting"
redirect shop
}
'*' { respond shop, [status: CREATED] }
}
}
This is my save method. Actuaally I didint write anything here. Generate domain .

Multipart post in grails causes 404 error

I try to upload data to a grails app. This works very good and the object is created in the database and the uploaded document is also present. Unfortunately i get a 404 error directly after the creation.
I am using grails 2.3.5 with the following code:
Action to save:
#Transactional
def save(Book bookInstance) {
if (bookInstance == null) {
notFound()
return
}
if (bookInstance.hasErrors()) {
respond bookInstance.errors, view:'create'
return
}
if(!bookInstance.id){
bookInstance.id = UUID.randomUUID().toString()
}
bookInstance.save flush:true
request.withFormat {
form {
flash.message = message(code: 'default.created.message', args: [message(code: 'Book.label', default: 'Book'), bookInstance.id])
redirect bookInstance
}
'*' {
respond bookInstance, [status: CREATED]
}
}
}
GSP:
<g:uploadForm action="save" class="form-horizontal">
<g:render template="form"/>
<div class="form-actions margin-top-medium">
<g:submitButton name="create" class="btn btn-primary" value="${message(code: 'default.button.create.label', default: 'Create')}" />
<button class="btn" type="reset"><g:message code="default.button.reset.label" default="Reset" /></button>
</div>
</g:uploadForm>
When the tag is used instead of the it works. The enctype="multipart/form-data" causes the error.
What can I try to solve this?
Thanks
You should check conf/Config.groovy and check that multipartForm: 'multipart/form-data', is present as a value for grails.mime.types, e.g.:
grails.mime.types = [
...
form: 'application/x-www-form-urlencoded',
multipartForm: 'multipart/form-data',
]
You also need to specify that it's a multipart form in your withFormat declaration:
request.withFormat {
form multipartForm
You can try 'render' or 'forward' instead of "respond" .

grails controllers errors

I have this DomainClass:
package cm
class XXX{
String city
String website
static constraints = {
city(nullable: true)
website(nullable: true)
}
static mapping = {
id column:'xxx_id'
city column: 'xxx_city'
website column: 'xxx_website'
table "xxx_XXX"
version false
}
}
The Controller:
class ConferenceController {
static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
def index = {
redirect(action: "list", params: params)
}
def list = {
params.max = Math.min(params.max ? params.int('max') : 10, 100)
[XXXInstanceList: XXX.list(params), XXXInstanceTotal: XXX.count()]
}
def save = {
def XXXInstance= new XXX(params)
if (!XXXInstance.save(flush: true)) {
render view: 'add', model: [XXXInstance: XXXInstance]
return
}
//flash.message = "${message(code: 'default.created.message', args: [message(code: 'person.label', default: 'Person'), personInstance.id])}"
redirect(uri:"/index.gsp")
}
}
and my add.gsp page:
<head>
<title> xXXx</title>
<meta name="layout" content="main2" />
</head>
...
<g:form controller="XXX" action="save">
<g:hasErrors bean="${XXXInstance}">
<div class="errors">
<g:renderErrors bean="${XXXInstance}" as="list" />
</div>
</g:hasErrors>
year
<g:textField name="year" /><br>
website
<g:textField name="website" /><br>
<g:submitButton name="save2" value="Save" />
</g:form></div>
</div>
...
</body>
With this current code, everything works fine, but when a contraint is failed, it is showns the corresponding error but the written values are gone.. I cant figure this out - i'v tried a lot of things, but im sure the solution is as easy as my question -.- Please help.
I think you should check the *.properties file in YOUR_PROJECT\grails-app\i18n folder. They have the definition for translation. Investigate it for a time and refer to the document if need, you will understand how Grails perform translation.
And uncomment the following line in your controller:
//flash.message = "${message(code: 'default.created.message', args: [message(code: 'person.label', default: 'Person'), personInstance.id])}"

Resources