Sending data to "View" from "Controller" - grails

In my controller class have the following code
class MyController {
def flickrService
def index = {
def data = flickrService.search {
tags 'tag,tag2,tag3'
page 3
perPage 14 // Look ma!
}
[urls:data.urls,page:data.page,pages:data.pages]
}
}
I have also created an index.gsp file.
As I am new to groovy grails - i could not figure it out how to access data returned by flickrservice in the view. Can I just access "data" defined above in the index view or I need to set it in the controller before I can loop through the returned data? Any help would be highly appreciated. Thanks

Yes, now you can access data from the view, for example,in index.gsp:
<html><head>Test</head><body>${urls} <br/> ${page} </body></html>
Generally saying, grails return the last value in function by default, so if you want to access many data, you can do like this:
class MyController {
def flickrService
def index = {
def data = ...
def data1 = ...
def data2 = ...
// Here's the return result:
[view_data:data,view_data1:data1, view_data2:data2]
}
}
Then you can access ${view_data},${view_data1},${view_data2} in view.

Related

GRAILS: findALL() vs FindBy---(params.id)

Greeting everyone,
I am trying to pass a parameters from a URL to a findAll() method.
LINE3 I use findAll() to define mouse.
LINE2 def house will bring in the parameter DELAWARE when I go to the page: http://localhost:8080/TestApp/home/county/DELAWARE
House will only show one instance instead of a list.. is there anyway to pass the url instead of ["DELAWARE"]? (please see line 3) thanks :)
def county() {
def house = Home.findByCounty(params.id) //sends only user related address to view
def mouse = Home.findAll("from Home h where h.county= ?", ["DELAWARE"]);
if (!house) {
response.sendError(404)
} else {
[house:house, mouse:mouse ]
}
}
Working Code +1 #Danilo
def county() {
def house = Home.findAllByCounty (params.id) //sends only county specified thru URL e.g. http://localhost:8080/TestAPP/home/county/DELAWARE
if (!house) {
response.sendError(404)
} else {
[house:house ]
}
}
findBy* will return at most one row, if you want to get all rows use findAllBy*
In order to understand how the URL will be used by Grails you have to have a look at conf/UrlMappings.groovy. You may find something like this:
static mappings = {
"/$controller/$action?/$id?(.$format)?"{
}
}
this means that when you call TestApp/home/county/DELAWARE what Grails is trying to do is use the home controller (HomeController), invoking the county method (def county(){...}) and passing DELAWARE as id.
This should work correctly if inside county method of the HomeController you have:
def filteredInstances = Home.findAllByCounty(params.id)

How to access a string from one method to another in one controller?

If we have one controller, let's call it document, that has two methods, one that uploads file and another that shows the uploaded file.
I would like to define a new string in the upload method that checks the size of the file and store a specific type name inside that string.
However I would like to access that string in another method which is the list method to be able to show it.
Here is my code:
Class DocumentController {
def list() {
//Here I would like to access that String to show it on the page
[fileSizeType: fileSizeType]
}
def upload {
//define the new String variable
String fileSizeType = ""
if(fileSize < 1000) {
fileSizeType = "type1.."
} else {
fileSizeType = "type2.."
}
}
}
In the gsp page I would like to access the string this way:
<td><g:link>\${fileSizeType}</g:link></td>
I am getting this error when I try the code above:
No such property: fileSizeType for class: file_down.DocumentController
You need to redirect to the list action while passing your argument in the params.
def upload() {
// simplify with ternary expression
def fileSizeType = (fileSize < 1000) ? "type1.." : "type2.."
redirect action:'list', params:[fileSizeType: fileSizeType]
}
// in your list action
def list() {
[fileSizeType: params.fileSizeType]
}

can't display model in gsp page

So I've just started using Grails/Groovy for my senior capstone project and I'm having a bit of a rocky start. The issue I'm having is when I set up a mapping of my model in the controller I can loop through it and print it to the console but when I try and access it from the view I get blank page.
The Domain class is simple:
package ot
class CrewDeskMapping {
String crewDesk
String desk
}
And the Bootstrap file that creates the test data:
...
new CrewDeskMapping(crewDesk:"North",desk:"MON1").save()
new CrewDeskMapping(crewDesk:"North",desk:"TWI1").save()
new CrewDeskMapping(crewDesk:"North",desk:"NWE1").save()
...
Here is my controller:
import ot.CrewDeskMapping;
class DashboardController {
def index() {
def desks = CrewDeskMapping.list()
[desks:desks]
for (d in desks) {
System.out.println(d.desk);
}
}
}
and the console output looks as it should:
MON1
TWI1
NWE1
CHI1
COL1
...
And the relevant part of my index.gsp
<body>
<g:each in="${desks}">
<p>Title: ${it.crewDesk}</p>
<p>Author: ${it.desk}</p>
</g:each>
</body>
The most perplexing part is if I try this same code but with a different Domain it works just fine. I've been at this problem for a couple days now with no avail so any help would be greatly appreciated!
def desks = CrewDeskMapping.list()
[desks:desks]
for (d in desks) { ...
does not return your [desks: desks]
Swap the for and the [desks: ...] or add a proper return statement at the end like this:
def index() {
def desks = CrewDeskMapping.list()
desks.each{ log.debug it.desk } // groovier debug print
// must be last in the method like a regular return in java,
// but groovy allows implicit return of the last statement
/*return*/ [desks:desks]
}

Multiple domain class binding in Grails controller action

Using grails 2.3.7. I am trying to use Grails controller action parameter binding. If I have this code:
class TestController {
def test(MyClass1 myClass1) {
log.debug(myClass1)
}
}
myClass1 is correctly fetched from DB using http://locahost:8080/myapp/test/test/1.
But now I want to pass two domain classes. I have tried this code:
class TestController {
def test(#RequestParameter('obj1') MyClass1 myClass1,
#RequestParameter('obj2') MyClass2 myclass2) {
log.debug(myClass1)
log.debug(myClass2)
}
}
And access using http://localhost:8080/myapp/test/test?obj1.id=1&obj2.id=3, nothing is fetched. Is this the right way to use data binding in controller actions? Or is this impossible?
Regards and thanks in advance.
You can use this and one of in your controller :
// binds request parameters to a target object
bindData(target, params)
// exclude firstName and lastName
bindData(target, params, [exclude: ['firstName', 'lastName']])
// only use parameters starting with "author." e.g. author.email
bindData(target, params, "author")
bindData(target, params, [exclude: ['firstName', 'lastName']], "author")
// using inclusive map
bindData(target, params, [include: ['firstName', 'lastName']], "author")
def User bindUser(params) {
def User user = new User()
def Human human = new Human()
bindData(user, params["user"])
bindData(human, params["humna"])
if(!human)
human.save(failOnError:true)
if(!user)
user.save(failOnError:true)
}
//alloha~
}

Grains repetead code for actions in controllers

I have already posted this question, but i realised the aswer was not what i was looking for. Imagine this controller:
class exampleController{
def action1 = {
...
[lala: lala, lele: lele]}
...
}
def action15 = {
...
[lala: lala, lele: lele]
}
I want to be able to return in all the action in this controller the same params. Imagining this:
def book = Book.findAllByIsbn(Isbn.get(1))
[book: book]
Is there any way of doing this, besides writing all the same code on all the actions? I have tried this method and it isnt working:
def action5 = {getModel()}
private getModel() {
def book = Book.findAllByIsbn(Isbn.get(1))
[book: book]
}
}
It is not working because, and my thought is, he doest accept multiple [return1: aaa, return2: bbb]. Any suggestion please ? I have also tried filters like in here: Grails controllers repeated code for all actions
but i couldnt managed to make it work. I would apreciated a detailed explanaintion about any of the solutions if possible:p Thanks in advanced,
VA
So it's not the same model, but a model with a repeated part.
You should know that the return value is an ordinary Map.
So, return value can be constructed like return getCommonModel() + [book: currentBook] where getCommonModel() returns another Map.
If you want to return the same model from all your actions, this approach should work:
class ExampleController {
def action5 = {getModel()}
def action1 = {getModel()}
//etc.
private getModel() {
def book = Book.findAllByIsbn(Isbn.get(1))
[book: book]
}
}
If you want to return the same model and render the same view from all your actions, you could return the same ModelAndView from each action, but then I would ask why do you need separate actions if they're all doing exactly the same thing?
I don't really understand your hypothesis
It is not working because, and my thought is, he doest accept multiple [return1: aaa, return2: bbb]
If your suggesting that getModel() can only return a model with a single entry, I find that very hard to believe. Can you elaborate a bit on this, or post some more information (e.g. stacktrace, unit test) that shows how/why it's not working?
Update
After reading your comments below I think I finally understand what you want to achieve, which is to append the model returned by getModel() (above) to the model returned by various other actions. Does this work:
class ExampleController {
def action5 = {
def action5Model = [foo: 'bar']
return addBookModel(action5Model)
}
def action1 = {
def action1Model = [foo2: 'bar2']
return addBookModel(action1Model)
}
//etc.
private Map addBookModel(Map model) {
def book = Book.findAllByIsbn(Isbn.get(1))
model.book = book
return model
}
}
This approach will only work when you want to add the book model within a single controller. If you want to add the book model in several controllers you can do this by:
putting addBookModel in an abstract class that the controllers extend
putting addBookModel in a class that is mixed-in with the controllers (using #Mixin)
putting addBookModel in a filter that is executed after the controller actions
If you are using exact same model in multiple pages. I would recommend you use a taglib for it.

Resources