Null Pointer Exception when running loop in GSP page - grails

I am trying to find the list of children of node, but every time I pass the node I am getting NullPointerException
<g:each in="${nodes}" var="node">
<g:if test="${node.parent == null }">
${node.id }-${node.label } //This works perfectly
<g:each in="${Node.findAllByParent(node)}" var="n">
${n.label}
</g:each>
</g:if>
</g:each>
The class looks like:
class Node {
String nodeId
String label
Node parent
}
I am getting a NullPointerException on the method findAllByParent on null object, even though the node does contain some information.

I expect that Node is in a package and if it is you either need to add an import to the top of the GSP...
<% import com.mypackage.Node %>
Or fully qualify the reference...
<g:each in="${com.mypackage.Node.findAllByParent(node)}" var="n">
You really shouldn't be initiating the query from a GSP to begin with, but that is a separate issue. One of the above should make your error go away.

Related

How to Remove a Polymer paper-listbox Item in an AngularDart Component

I generate a paper-listbox as follows:
<paper-listbox class="scroll-list gutter" id="index">
<paper-item class="index-entry" *ngFor="let composition of compositions" [class.selected]="composition == selectedComposition" (click)="onSelect(composition)">
{{ composition.name }}
</paper-item>
</paper-listbox>
I have a method that deletes an item from the database. I want to remove the corresponding entry from the list as well. I found this stackoverflow question and tried it. It gave a no such method error when I ran it. Then I tried:
PaperListbox index;
...
index = querySelector('#index');
...
index.remove();
It removes the entire listbox. I was in the ball park so I tried:
index.selectedItem().remove();
That gave me the browser console error:
ORIGINAL EXCEPTION: Class 'PaperItem' has no instance method 'call'.
NoSuchMethodError: method not found: 'call'
Receiver: Instance of 'PaperItem'
Arguments: []
Given that the error mentions paper-item makes me think I'm getting close, but I'm out of ideas. How does one delete a paper-listbox item? For extra credit, how does one add an item? That's my next task.
Just remove the item from composition and *ngFor updates the list of <paper-item ...> entries automatically.

Grails cannot display state name in search results page

I've set up a search page in my Grails application using the searchable plug-in. My search is working fine but I'm running into a small problem. In my search results (which display a name and a state), the state is not showing up.
I have two domains:
class Person {
String firstName
String lastName
State state
}
class State {
String name
String code
String toString()
return this.name
}
}
In my search.gsp view, I have the following:
<g:each var="result" in="${searchResult.results}">
<div class="searchResult">
<div class="searchPerson">
<g:link controller="person" action="show" id="${result.id}">
${result.lastName}, ${result.firstName}
</g:link>
</div>
<div class="searchAddress">
${result.state}
</div>
</div>
</g:each>
How come my state name is not showing up? I've tried the following:
${result.state.name}
${result.state.code}
${result.state.toString()}
I'm sure the issue is a small one but, as a Grails newcomer, I can't seem to figure it out. I'd appreciate any help!
Found this (Eager fetching and searchable plugin in Grails), seems like what is causing the problem, hope your problem gets resolved.

Grails "bean:input" (bean fields) showing the wrong bean property

Since we've updated to grails 2.0.1 (from 2.0.0) all of our beans shown via bean fields are incorrectly displayed as the first property of that "withBean" field. In the example I've posted below, all of [firstName, lastName, dateOfBirth, contactNumber] are shown as just 'firstName' (we know it's not just the messages which are wrong because otherwise the 3rd property (dateOfBirth) would be a date picker, not just a text field).
Any potential workarounds or suggestions?
(plugins.bean-fields=1.0-RC3)
I encountered the same problem, and have a work-around.
I has customised beanfield templates extracted into a gsp template called /shared/_beanfieldConfig.gsp , which I then included by rendering before calling any beans tags. e.g.
<g:render template="/shared/beanFieldConfig" />
<bean:withBean beanName='command'>
<bean:input property='username' />
This worked nicely in 1.3.7, and meant I could share beanFieldConfig between views.
When upgrading to 2.0.3, I enountered the same issue as the original question. I've found I can work around this by inlining the content of my _beanFieldConfig in each view.
Yuk, but at least it means I don't need rewrite all my views to use the replacement plugin (yet).
(edit)
Interestingly, although beanField config in a render'd template doesn't work, sticking it in a taglib DOES.
so, while previously I had in beanFieldConfig
<bean:inputTemplate>
<div class='input ${errors ? 'errors' : '' }'>
${label}
${field}
<g:if test="${errors}">
${errors}
</g:if>
</div>
</bean:inputTemplate>
If I define the equivalent tag -
def beanFieldConfig = {
bean.inputTemplate { m ->
m.with {
""" <div class='input ${errors ? 'errors' : '' }'>
${label}
${field}
${errors ?: ''}
</div>"""}
}
}
and then in my gsp replace <g:render template="/shared/beanFieldConfig" /> with <g:beanFieldConfig/>, it works.

Grails grailApplication.controllerClasses sort controller by package

I have the following code that grabs all controllers, sorts it, and outputs in li tags:
<g:each var="c" in="${grailsApplication.controllerClasses.sort { it.fullName } }">
<li<%= c.logicalPropertyName == controllerName ? ' class="active"' : '' %>>
<g:link controller="${c.logicalPropertyName}">${c.naturalName}</g:link>
</li>
</g:each>
I have a need to filter out controllers by package i.e. grab controller from a certain package.
For example:
com.app.module.mars.controller.HelloController
com.app.module.venus.controller.PrintController
As you can see I'm packaging controllers by modules, so mars will have its own set of controllers and venus will have its own. Then in the UI I want to use the above code (with some filter) which will show modules as main-menus and their controllers as dropdowns.
How can I apply such a filter? Or if you could guide me in the right direction would be great. Thanks.
You can use GrailsClassUtils.isClassBelowPackage() which takes a class and a list of packages as the arguments. So this should do the trick:
GrailsClassUtils.isClassBelowPackage(c.class, ['com.app.module.mars'])
Edit: grailsApplication.controllerClasses probably gives you a list of GrailsClass objects, so you'd want to use c.clazz instead of c.class like
grailsApplication.controllerClasses.each { c ->
GrailsClassUtils.isClassBelowPackage(c.clazz, ['com.app.module.mars'])
}
You can use Collection#groupBy to group the controller classes by package name.
I don't have a Grails system to make a quick test right now, but this would be a little example of grouping classes by package name:
def classes = [Integer, List, String]
def classesByPackage = classes.groupBy { it.package.name }
assert classesByPackage == ['java.lang': [Integer, String], 'java.util': [List]]
You can then iterate through each packageName to make each menu and through each class under that package name to make each menu item. Something like...
classesByPackage.each { packageName, packageClasses ->
println "Menu $packageName"
packageClasses.each { println " Item $it.simpleName" }
}
... but with GSP-style loops :)

a list of checkboxes

I have two domain classes
class Contract {
String number
static hasMany = [statements:Statement]
}
class Statement {
String code
static hasMany = [contracts:Contract]
}
I would like to show all statements available in my gsp with a checkbox next to each, allowing the user to choose which statements are applicable to the contract. So something like:
[ ] Statement Code 1
[ ] Statement Code 2
[ ] Statement Code 3
I started off with this:
<g:each in="${Statement.list()}" var="statement" status="i">
<g:checkBox name="statements[${i}].id" value="${statement.id}" checked="${contractInstance.statements.contains(statement.id)}" />
<label for="statements[${i}]">${statement.code}</label>
</g:each>
But i just cannot get a list of checked statements to the controller (there are null elements in the list, there are repeated statements...).
Any idea how to achieve this?
This is possible, but it does require a bit of a hack. First off, every checkbox must have the same name, "statements":
<g:each in="${org.example.Statement.list(sort: 'id', order: 'asc')}" var="statement" status="i">
<g:checkBox name="statements" value="${statement.id}" checked="${contract.statements.contains(statement)}" />
<label for="statements">${statement.content}</label>
</g:each>
Second, in the controller you have to remove the "_statements" property before binding:
def contract = Contract.get(params.id)
params.remove "_statements"
bindData contract, params
contract.save(failOnError: true)
The check box support hasn't been designed for this use case, hence the need for a hack. The multi-select list box is the one typically used for this type of scenario.
I personally prefer to get the list of Id's in this case.
<g:each var="book" in="${books}">
<g:checkBox name="bookIds" value="${book.id}" ...
</g:each>
Command Object:
class BookCommand {
List<Serializable> bookIds
}
In controller action:
BookCommand bc ->
author.books = Book.getAll(bc.bookIds)
Change the checkbox to something like this.
<g:checkBox name="statements.${statement.id}" value="true" checked="${contractInstance.statements.contains(statement)?:''}" />
and then in the controller, in params.statements you will get a list with the IDs of the checked statements.
Also notice the ?:'' in the checked property, it's a good idea to add it because any value(even 'false') in the checked property is interpreted as checked.
Are you mapping request directly to Contract? It's much more secure to map incoming request into an Command object.
As about mapping a list - values are mapped only to existing elements. I mean it cannot create new list elements. You need to prepare it before mapping. If you know that there is always 3 elements, you can make:
class ContractCommand {
List statements = [
new Statement(),
new Statement(),
new Statement(),
]
}
and map request to this object

Resources