I'm using Grails 2.1.1 with mongodb plugin. I have problem with changing order of columns in generated list. As grails scaffolding guide says you need only properly order attributes in contraints block.
My domain:
class Section {
String idName
String visible
String required
String name
String bold
static embedded = ['question']
List<Question> questions
static hasMany = [questions : Question]
static constraints = {
idName (blank: false)
name (blank: false)
visible (blank: false)
required (blank: false)
bold (blank: false)
}
@Override
public String toString() {
name
}
}
but columns are still ordered alphabetically. I'm using static scaffolding, so after changes in constraints i use grails generate-all *
command and override all files.
And yes, I tried cleaning and compiling code, also cleaning and restarting server (this integrated with STS) and cleaning browser cache. Is there problem with mongo database (hibernate plugin is uninstalled)?
After that I also installed grails templates. In list.gsp there is line with sorting attributes:
Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[]))
Any idea how can i change this to get working order that I set in constraints?
A jira issue should be filled. If one looks at https://github.com/grails/grails-core/blob/master/grails-crud/src/main/groovy/org/codehaus/groovy/grails/scaffolding/DefaultGrailsTemplateGenerator.groovy
void generateView(GrailsDomainClass domainClass, String viewName, Writer out) {
def templateText = getTemplateText("${viewName}.gsp")
if (templateText) {
def t = engine.createTemplate(templateText)
def multiPart = domainClass.properties.find {it.type == ([] as Byte[]).class || it.type == ([] as byte[]).class}
boolean hasHibernate = pluginManager?.hasGrailsPlugin('hibernate')
def packageName = domainClass.packageName ? "<%@ page import=\"${domainClass.fullName}\" %>" : ""
def binding = [pluginManager: pluginManager,
packageName: packageName,
domainClass: domainClass,
multiPart: multiPart,
className: domainClass.shortName,
propertyName: getPropertyName(domainClass),
renderEditor: renderEditor,
comparator: hasHibernate ? DomainClassPropertyComparator : SimpleDomainClassPropertyComparator]
t.make(binding).writeTo(out)
}
}
It is clear that the call generate views decides to use SimpleDomainClassPropertyComparator. Grails was originally built to depend on hibernate. Over the last couple of years, the world has been using additional persistance mechanisms. If one looks at DomainClassPropertyComparator, there is no dependency on hibernate. I feel the code should test if the domainObject "hasConstraints" to decide which comparator to use or simple use DomainClassPropertyComparator by default. Its behavior is the same if no constraints are found. The call to "hasHibernate" should not be needed by DefaultGrailsTemplateGenerator.
As a work around, you can install the scaffolding templates, edit _form.gsp and change the comparator it is using to DomainClassPropertyComparator e.g. my _form.gsp
<%=packageName%>
<% import grails.persistence.Event %>
<% import org.codehaus.groovy.grails.scaffolding.DomainClassPropertyComparator %>
<% excludedProps = Event.allEvents.toList() << 'version' << 'dateCreated' << 'lastUpdated'
persistentPropNames = domainClass.persistentProperties*.name
boolean hasHibernate = pluginManager?.hasGrailsPlugin('hibernate')
if (hasHibernate && org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder.getMapping(domainClass)?.identity?.generator == 'assigned') {
persistentPropNames << domainClass.identifier.name
}
DomainClassPropertyComparator mattsComparator = new DomainClassPropertyComparator(domainClass)
comparator = mattsComparator
props = domainClass.properties.findAll { persistentPropNames.contains(it.name) && !excludedProps.contains(it.name) }
Collections.sort(props, comparator)
for (p in props) {
if (p.embedded) {
def embeddedPropNames = p.component.persistentProperties*.name
def embeddedProps = p.component.properties.findAll { embeddedPropNames.contains(it.name) && !excludedProps.contains(it.name) }
Collections.sort(embeddedProps, comparator)
%><fieldset class="embedded"><legend><g:message code="${domainClass.propertyName}.${p.name}.label" default="${p.naturalName}" /></legend><%
for (ep in p.component.properties) {
renderFieldForProperty(ep, p.component, "${p.name}.")
}
%></fieldset><%
} else {
renderFieldForProperty(p, domainClass)
}
}
private renderFieldForProperty(p, owningClass, prefix = "") {
boolean hasHibernate = pluginManager?.hasGrailsPlugin('hibernate')
boolean display = true
boolean required = false
if (hasHibernate) {
cp = owningClass.constrainedProperties[p.name]
display = (cp ? cp.display : true)
required = (cp ? !(cp.propertyType in [boolean, Boolean]) && !cp.nullable && (cp.propertyType != String || !cp.blank) : false)
}
if (display) { %>
<div class="fieldcontain \${hasErrors(bean: ${propertyName}, field: '${prefix}${p.name}', 'error')} ${required ? 'required' : ''}">
<label for="${prefix}${p.name}">
<g:message code="${domainClass.propertyName}.${prefix}${p.name}.label" default="${p.naturalName}" />
<% if (required) { %><span class="required-indicator">*</span><% } %>
</label>
${renderEditor(p)}
</div>
<% } } %>
If you comment the line below in the template and regenerate the view, the order in the constraints will be the order in scaffolding
//Collections.sort(props, comparator.constructors[0].newInstance([domainClass] as Object[]))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With