I have a domain class with the attributes start + end, both of them are LocalTime (Joda-Time plugin). I want the end Time to be nullable. For this purpose I used the following constraint: end nullable: true. Scaffolding is realized through the Joda template and it's working pretty good. The only problem is that selecting nothing with the timepicker for the end property results in: Cant populate a class org.joda.time.LocalTime without a hour.
This is the generated code in the view:
<div class="fieldcontain ${hasErrors(bean: dailyBookingInstance, field: 'end', 'error')} ">
<label for="end">
<g:message code="dailyBooking.end.label" default="End" />
</label>
<joda:timePicker name="end" value="${dailyBookingInstance?.end}" default="none" noSelection="['': '']"></joda:timePicker>
</div>
This is a binding error - Joda Time Plugin - Fields nullable?
One work around is--
Change field name in the view, say time
<joda:timePicker name="time" value="${myDomainInstance?.end}" default="none" noSelection="['': '']"/>
and only populate this in your domain instance if data exists, like this
def save(MyDomain myDomainInstance) {
if(params.time_minute && params.time_hour){
myDomainInstance.end = new LocalTime(params.int('time_hour'), params.int('time_minute'))
myDomainInstance.validate()
}
//Other save code
}
Hope this helps..,.
Related
The bean class looks like this:
String houseNo
String address
Person person
The view looks like this
<g:form action="save">
<fieldset class="form">
<g:render template="form" />
</fieldset>
<fieldset class="buttons">
<g:submitButton name="create" class="save"
value="${message(code: 'default.button.create.label', default: 'Create')}" />
</fieldset>
</g:form>
According to my knowledge in Grails, i think is <g:render template="form" /> will pull all form attributes and display it.
But what i want to do is Instead of displaying a drop-down for Person, i want to display all Person related fields like personName, personAge. How can i display these fields in a label underneath ?
Help
You're correct about the way g:render works, the template part refers to a GSP which will look through the bean values and print them according to the html + groovy markup in "_form.gsp" (located in your views folder under the controller name).
To change the way the Person domain object is displayed, simply edit this "_form.gsp" and take out the 'select' html code - replacing it with groovy markup using the property values of the bean, eg.
${beanName.person.personName} //(use the existing code to help workout the bean name etc)
Hopefully that helps you on your way.
I'm using Grails 2.2.3 and Fields plugin 1.3.
I want to customize fields to manage one-to-many relationships using select tag.
In views/_fields/oneToMany/_input.gsp I have:
<g:select name="${property}.id" from="${type.list()}" optionKey="id" value="${value}" class="form-control one-to-many" noSelection="['null': "${label}"]" />
But type is a set, so I can't use list function.
How can I retrieve target domain class?
As long as you use a Map to declare the relationship, for example:
static hasMany = [ books: Book ]
You can get the list of the referenced domain, which is the key from the hasMany property of the bean, so the from attribute should change to
from="${bean.hasMany[property].list()}"
Alternatively you can pass the list to the _input.gsp template prefixing the variable name with input-, e.g.
<f:field property="books" input-domainList="${bookInstaceList}" />
In the _input.gsp template you can use the variable as follows:
from="${domainList}"
or mixing both methods:
from"${domainList ?: bean.hasMany[property].list()}"
I found this solution for the problem, this code work fine with one to many and one to one
<div class="input-group">
<g:select name="${persistentProperty.toString().contains('one-to-many')?property:property+'.id'}" value="${value?.id}" required="${required}"
noSelection="${['null':'Escriba...']}" class="select2 col-md-6"
multiple="${persistentProperty.toString().contains('one-to-many')?true:false}" from="${grailsApplication.getDomainClass(persistentProperty.properties['associatedEntity'].toString()).clazz.list()}"
optionKey="id"></g:select>
</div>
This solution can be helpful. I found in the documentacion of Fields Plugin, the persistentProperty is a class type DomainProperty but their methods doesn't works and I found the correct class is org.grails.datastore.mapping.model.MappingFactory
you can use .toArray() method on your Set instead of .list().
ale
You can use the code below to identify the Element of your collection
def className = bean.hasMany[property].properties.typeName
See my "views/_fields/oneToMany/_input.gsp" implementation:
<%# page defaultCodec="html" %>
<%
def className = bean.hasMany[property].properties.typeName
def simpleName = Class.forName(className).simpleName
def beanSimpleName = bean.class.simpleName
def createUri = "/${simpleName.toLowerCase()}/create?${beanSimpleName.toLowerCase()}.id=${bean.id}"
%>
<a id="add${simpleName}" name="add${simpleName}" href="${createLink(uri: "${createUri}")}">
Add ${simpleName}
</a>
<ul>
<g:each var="item" in="${value}">
<li>
${item}
</li>
</g:each>
</ul>
I'm starting with Grails and I don't know how should I face the following use case.
The app is about sports results prediction, so I have in my domain "Match" and "Prediction", and I want to have one view where the user can update all the predictions of matches that haven't been played yet.
So far I've defined a method in my "PredictionController" that searches all the already existing predictions of games that have to be played and generates new Prediction instances for any new Match with a date higher than now. I've created a view for that method and I'm getting correctly all the predictions that I should complete or update, and I've defined in my controller another method for the form sumbission (so I'm trying to resolve this in the same way that the 'create' and 'update' scaffolded methods work).
My question is, How can I access to all the Predictions modified by my view? How can I send all the predictions to my update method? Is it defining a hidden field with a variable containing all the collection?
This is the form in my GSP view:
<g:form action="savePredicctions">
<fieldset>
<g:each in="${predictions}">
<li>
<div>
${it.match.homeTeam}
<g:field name="${it.match}.homeGoals" type="number" value="${it.homeGoals}" />
</div>
-
<div>
<g:field name="${it.match}.awayGoals" type="number" value="${it.awayGoals}" />
${it.match.awayTeam}
</div>
</li>
</g:each>
</fieldset>
<fieldset class="submit">
<g:submitButton />
</fieldset>
</g:form>
You can use a command object to store the instances of Prediction.
#Validateable
class PredictionCommand {
//data binding needs a non-null attribute, so we use ListUtils.lazyList
List<Prediction> predictions = ListUtils.lazyList([], FactoryUtils.instantiateFactory(Prediction))
}
In your view, you need to control the index of your list, and send the attributes of Prediction to the controller:
<g:each in="${predictions}" status="i">
<g:textField name="predictions[$i].homeGoals" />
<g:textField name="predictions[$i].awayGoals" />
</g:each>
And in your controller you can use bindData() to bind params to your command:
class CommandController {
def save() {
PredictionCommand command = new PredictionCommand()
bindData(command, params)
println command.predictions
}
}
Say I have a Domain object Teacher with two fields String name, TeacherType teacherType, where TeacherType is an enum containing AssitantProfessor, AssociateProfessor, Professor.
After I generate the views using grails run-target generate-all Teacher, it produces an _form.gsp that is used for both create and edit of Teacher. In the edit view I want only the name to be editable but the TeacherType to be unmodifiable once created (this is just an example, it is a requirement that certain fields can't be updated after creation). In the create view, both TeacherType and name should be editable.
Since both create.gsp and edit.gsp render the _form template, what is the preferred approach here?
Create two separate templates i.e. _formCreate.gsp , _formEdit.gsp; Or
Pass in a model map within create.gsp and edit.gsp and use them in _form.gsp to conditionally render the view?
e.g.
In create.gsp:
<fieldset class="form">
<g:render template="form" model="[teacherInstance: teacherInstance, 'mode':'create']"/>
</fieldset>
In edit.gsp
<fieldset class="form">
<g:render template="form" model="[teacherInstance: teacherInstance, 'mode':'edit']"/>
</fieldset>
In _form.gsp
<g:if test="${mode == 'edit'}">
<g:select name="teacherType" from="${TeacherType?.values()}" keys="${TeacherType.values()*.name()}" required="" value="${teacherInstance?.teacherType?.name()}" disabled="disabled"/>
</g:if>
<g:else>
<g:select name="teacherType" from="${TeacherType?.values()}" keys="${TeacherType.values()*.name()}" required="" value="${teacherInstance?.teacherType?.name()}" disabled="false"/>
</g:else>
Approach 2 works but I suppose if the number of conditional statements increase it may just be better to follow approach 1 and split the forms.
Is there another approach that I'm not aware of?
The disabled attribute of <g:select> (and many other <g:...> form field tags) can be a boolean-valued expression:
<g:select name="teacherType" from="${TeacherType?.values()}"
keys="${TeacherType.values()*.name()}" required=""
value="${teacherInstance?.teacherType?.name()}"
disabled="${mode == 'edit'}"/>
This will render as disabled="disabled" if the expression evaluates to true, and as the absence of a disabled attribute (i.e. the field will not be disabled) if the expression is false. You could even use a boolean entry in the model, e.g. render the template with
model="[teacherInstance: teacherInstance, editing:true]"
(or editing:false respectively) and then say disabled="${editing}" on the <g:select>.
I need to create a custom gsp whose domain model is designed as follows
class Question {
SortedSet<Choice> choiceCollection;
static hasMany = [choiceCollection:Choice]
static mappping = {
choiceCollection(joinTable:false)
}
}
Each Question object has five Choices. So, i create the following snippet of code
create.gsp
<g:each var="i" in="${(1..5)}">
<div class="fieldcontain required">
<label for="description">
Option ${i}.
<span class="required-indicator">*</span>
</label>
<g:textArea name="choiceCollection[${i}].description" cols="40" rows="5" maxlength="2000" value="${questionInstance?.choiceCollection[${i}]?.description}"/>
</div>
</g:each>
Although Grails GSP engine complains Unclosed GSP expression which is not true - g:textArea is closed as you can see above -, i believe the real problem is the expression
${questionInstance?.choiceCollection[${i}]?.description}
which involves nested GSP expressions.
Question: am i missing some feature ? If so, what should i do to overcome my obstacle ?
Grails version: 2.1.1
Shouldn't
${questionInstance?.choiceCollection[${i}]?.description}
be
${questionInstance?.choiceCollection[ i ]?.description}
The set bit:
Try something like:
<g:each var="choice" status="i" in="${questionInstance?.choiceCollection}">
So i still contains your index, but choice contains what you were trying to get with questionInstance?.choiceCollection[${i}]