In a controller, I have populated a map that has a string as key and a list as value; in the gsp, I try to show them like this:
<g:each in="${sector}" var="entry" >
<br/>${entry.key}<br/>
<g:each in="${entry.value}" var="item" >
${item.name}<br/>
</g:each>
</g:each>
The problem is that item is considered as string, so I get the exception
Error 500: Error evaluating expression [item.name] on line [11]:
groovy.lang.MissingPropertyException: No such property: name for class:
java.lang.String
Any hints on how to fix it other than doing the find for the item explicitly in the gsp ?
I did the poc which works fine for me
class Item{
String name
}
List items = [new Item(name:"laptop" ,
new Item(name:"mouse")]
Map sector =[:]
sector.manager = items
sector.manager.each{item->
println item.name
}
Even If it doesn't work, Try declaring Map sector as
Map < String, List < Item > > sector =[:]
Related
I'm just inquisitive if this is possible. If so, please help me.
Everything is already set and valid like the:
-Model.info:
public class info{
public string information{get;set;}
}
-ViewBag.Infos:
ViewBag.Infos = new SelectList(new []{"Option1","Option2"});
-I am not finding or encountering an error.
So it goes like this:
#foreach(var nom in Model.info)
{
#Html.DropDownList("Infos",new{#Value = "nom.information"})
}
Is it possible to put the foreach value of nom into each dropdownlist's value?
First error is that you are iterating over Model.info that is an string (is an iteration over every char, the type of nom would be char).
By the other hand, you must define a DropDownList with the ViewBag elements, something like that:
#Html.DropDownList("info", ViewBag.info, null, Model.info)
lets say i have this:
ArrayList maps = [ ]
Map map = [:]
my controller i did that:
List.each {
myList -> map = [key1:value1,key2:value2,key3:value3]
maps << map
}
return render ( template: "myTemplate" , model: [arrayList:maps])
I'm passing this arrayList of maps to my GSP and iterating through it so i assign the values of each map to elements.
i did something like this in my gsp.
<g:each in="${arrayList}" var="map">
<g:select from="${someList}" optionValue="${map.get('key1')}" optionKey="key"/>
<input type="text" id="textBox" value="${map.get('key2')}"/>
</g:each>
i am getting this error ! which says:
ERROR errors.GrailsExceptionResolver - MissingPropertyException occurred when processing request: [POST] .....
No such property: myValue for class: java.util.LinkedHashMap$Entry. Stacktrace follows:
groovy.lang.MissingPropertyException: No such property: myValue for class: java.util.LinkedHashMap$Entry
at Users_**_Projects_**_grails_app_views__myGsp_gsp.run(_myGsp.gsp:6)
at org.grails.plugins.web.rest.api.ControllersRestApi.render(ControllersRestApi.groovy:53)
at se.su.it.vfu.ConfigController$$EPLhPshc.myFunction(myController.groovy:428)
myGsp.gsp:6: is actually the "select" row provided in the gsp code
and 428 in my controller is the return render () row
myValue is actually a map value!
I am iterating through the arrayList and the first map is map1 looks like this
[key1: myValue , key2: otherValue , key3 : someOtherValue]
You have the following in your GSP:
<g:select from="${someList}" optionValue="${map.get('key1')}" optionKey="key"/>
That is going to be the problem. The value that you assign to optionValue should be the name of a property on the elements in someList. That property will be used when generating the "value" of the individual elements in the list. In your case it looks like map.get('key1') evaluates to myValue so the select tag is going to try and retrieve the value of the myValue property for each element in the list.
See http://grails.github.io/grails-doc/3.0.4/ref/Tags/select.html for more details.
I hope that helps.
Fairly new to the Grails model, and having a little trouble getting around using a service for my database transactions.
Service:
class ReportService {
def dataSource
def listDatatypeValues(Datatype dt) {
def sql = new Sql(dataSource)
def list = sql.rows (dt.statement)
return list
}
}
Controller:
def run(Long id) {
def reportInstance = Report.get(id)
def listPromptValues = populatePrompts(reportInstance)
if (!reportInstance) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'report.label', default: 'Report'), id])
return
}
[reportInstance: reportInstance, listPromptValues: listPromptValues]
}
def populatePrompts(Report rp){
//for a prompt in the report, go out and get it's values
rp.prompts.each {
List list = reportService.listDatatypeValues(it.datatype)
}
}
View snippet:
<g:if test="${reportInstance?.prompts}">
<li class="fieldcontain">
<g:each var="prompt" in="${reportInstance.prompts}">
<g:if test="${prompt.datatype.type == 'DropDown'}">
<g:select id="prompt.name" from="${listPromptValues}" name="prompt.name" value="" noSelection="['':'']"/>
</g:if>
</g:each>
</li>
</g:if>
We have a report object, that contains prompts, which in turn contain a datatype. For any given report, when it is pulled up on the UI, it will give the report details, and then list the prompt value for a give prompt. The problem is the current setup is listing the object reference as the prompt value and not the list of values returned from the service.
And example would be Report 1 has 2 prompts, Starting Term Code and Ending Term Code. Both of them use Term Code as the datatype since it is the same SQL query, and the list returned from listDataTypeValues would be a list of 70+ term codes that are stored in the database.
Any thoughts or direction?
I tried following along with this but I can't get it to work.
Thanks!
Your populatePrompts function isn't returning a meaningful value. If you iterate with collectMany instead of each the value of the expression will be the concatenation of all the results from your queries. Try something like this:
def populatePrompts(Report rp){
rp.prompts.collectMany {
reportService.listDatatypeValues(it.datatype)
} //.unique()
}
You may also want to call unique on the result to avoid duplicates in your g:select input.
Suppose I have two domain objects, Document and Author
Class Document {
Author author
String title
}
Class Author {
String lastName
String firstName
String toString() {
return lastName + ", " + firstName
}
}
The view list.gsp looks something like this:
<g:sortableColumn property="title" title=... />
<g:sortableCOlumn property="author" title=... />
....
<td>${fieldValue(bean: documentInstance, field: "author"}></td>
<td>${fieldValue(bean: documentInstance, field: "title"}></td>
The displayed values in the table work as intended - the table row will show the author as (lastName, firstName) next to documentInstance.title.
However, clicking the Author column header to sort causes "documents" to be sorted by author.id .
What is the most expedient way to get sorting by author.toString() or "author.lastName, author.firstName" instead of sorting by author.id?
I'd prefer to avoid falling back to .withCriteria{} if possible - I have four different columns that need this functionality, and it seems like that would get messy.
You could use a derived property to create a virtual column to sort on:
Class Author {
String lastName
String firstName
String sortingName
static mapping {
// modify the SQL formula to use your DB's concatenation operator
sortingName formula: "`LAST_NAME` || ',' || `FIRST_NAME`)" // Standard SQL
}
String toString() { sortingName }
}
Then set your column to sortingName:
<g:sortableColumn property="author.sortingName" title=... />
(I'm kind of guessing here, but I think this should work.)
I'm just a Grails beginner so maybe my answer is not optimal, but this was the easiest way for me:
Instead of using Document.list(params) I used Document.findAll(). Is worth mentioning that in my application I do needed some kind of filter in my lists, so findAll() was the best approach. Anyways, here is how I would do it:
Document.findAll( "from Document as d order by d." + params.sort + ' ' + params.order, params ) //supports pagination
And in the View:
<g:sortableCOlumn property="author.lastName" title=... />
I'm struggling to get a g:each tag to work. What I'm passing to the view is a list of hashmaps (something like this [ [ : ] , [ : ] ] ).
Each hashmap is of the form [location: somelocation , artist: someartist].
The code is the following:
CONTROLLER
in the controller I'm passing the following:
[searchedResults : results.searchedResults]
VIEW
<g:each status="i" in="${searchedResults}" var="results">
if(results.location!=null){
var point${results.location.id} = new google.maps.LatLng(${results.location.lat}, ${results.location.lng});
var myMarkerOptions${results.location.id} = {
position: point${results.location.id},
map: map
};
var marker${results.location.id} = new google.maps.Marker(myMarkerOptions${results.location.id});
}
</g:each>
Any ideas why this wouldn't work?
Thanks!
GrailsGuy is right in that you can't write groovy code in the body of an each tag like that. But let me try and convert it to something for you, since it looks like your doing some javascript in there as well...I think all you need to fix is your if statement
<g:each status="i" in="${searchedResults}" var="results">
<g:if test="${results.location}">
//everything else seems like it would work, assuming your javascript
// code is accurate
</g:if>
</g:each>