I am maintaining a grails 1.1.1 application. There is an include code which works if we include from a regular gsp. But when I try to include it from _header.gsp it doesn't work. I am using exactly the same statement. It actually calls the method in the controller but nothing gets returned in the view.
Following is the code which works from a regular gsp
<g:include controller="abcGenericComponent" action="visitOurBoardsComponent" />
This is the method in controller
def visitOurBoardsComponent = {
def visitOurBoardsContent = abcGenericComponentService.getVisitOurBoardsComponent(request)
log.debug "Calling vistitboards ${visitOurBoardsContent}"
[visitOurBoardsContent: visitOurBoardsContent]
}
The log statement is showing up in the logs. That means the method is getting executed.
This is the included gsp
<ul>
<g:each var="ourBoards"
in="${visitOurBoardsContent}">
<li>
${ourBoards?.displayName}
</li>
</g:each>
Related
I'm creating a Grails app following this tutorial: http://grails.asia/grails-tutorial-for-beginners-display-data-from-the-database
When I try to display data from database though, nothing happens. Below is my controller code:
def index(){
def users = User.list();
[users:users]
}
def displayUsers(){
if(User.count()==0){
render 'User list is empty!';
}else {
render(view: 'userlist.gsp');
//a little test
println User.list().size();
println User.count();
for(User u : User.list()){
println u.username;
}
}
}
The User.count() is working, because I can see the usernames in console and userlist.gsp renders every time, but it seems that my view code doesn't see the list. Here's the userlist.gsp code:
<body>
userlist.gsp
<g:each in="${users}" var="user" status="i">
<h3>${i+1}. ${user.username}</h3>
</g:each>
</body>
What can be wrong with this code? I've been making precisely the same steps as in the tutorial above in my analogical app, but it doesn't seem to work. This is especially weird, since I've found a similar question under this link: grails: show list of elements from database in gsp
and it's been marked as accepted answer. Why does exacly the same way not work in my app?
render gsp view as follows (pass data as a model).
render(view: "userlist", model: [userList : User.list()])
Now get model data in gsp as follows.
<body>
userlist.gsp
<g:each in="${userList}" var="user" status="i">
<h3>${i+1}. ${user.username}</h3>
</g:each>
</body>
You can do with many options:
rename your gsp action in controller from def index() to def userlist()
or rename index.gsp file to userlist.gsp
you can redirect to userlist.gsp with ${users} object
So change in controller def index() action
[users:users] to redirect(action: "userlist", params: ["users": users])
Note: 2nd method will show parameters in url.
Refer Grails Doc
You can use chain
e.g. chain(action: "userlist", model: ["users": users])
Refer Grails Doc
every gsp action (page) needs to be injected
I'm having difficulties getting my ajaxform working properly. I'm using Grails 2.4.4 and have the following remoteForm code.
view usedProducts
<div id="updateMe">
<g:each in="${productList}" var="product">
${product.item} Success1
</g:each>
</div>
<g:formRemote name="myForm"
url="[controller:'product', action: 'save']" update="updateMe">
<g:textField name="item" required="" value="${newProduct?.item}" />
<g:submitButton name="Save" />
</g:formRemote>
Controller ProductController
def usedProducts = {
[productList:Product.findAll()]
}
#Transactional
def save(Product productInstance) {
productInstance.save flush:true
[productList: Product.findAll()]
}
Console Error
POST http://localhost:8080/TekDays/product/save
404 Not Found
54ms
jquery-...e=false (line 9631)
"NetworkError: 404 Not Found - http://localhost:8080/TekDays/product/save"
I'm afraid you cannot do that this way you're trying to do.
Note that when the AJAX call is effectively being performed by the user there are no more GSP tags. There are only CSS, HTML and Javascript. It's the browser world.
Please put the render in front of what you're returning and test.
#Transactional
def save(Product productInstance) {
productInstance.save flush:true
render Product.findAll()
}
You'll see that the content of the DIV updateMe will be replaced by the content rendered by the save method. The content is a list returned by findAll method with all Product objects.
When you use render the content returned (a GSP template, the content of a variable or a HTML) will be rendered in the current HTML, for instance, through an AJAX call.
For other side when you use the return keyword is expected a GSP with the same name as the controller method. Because of that you're getting a 404, since a save.gsp isn't found. Note: if you omit the return keyword (as you're doing) then the groovyc (Groovy compiler) will implicitly put it for you.
If I understand well what you're trying to do then you must render the content (not return it).
I've got a controller, which is getting a list of objects associated with a user and passing it to the view using the render method, like so:
class HomeController {
def index() {
def postList = user.posts
postList.each{ it ->
println "Title: " + it.title
}
render(view: "/index", model: [returnPosts: postList])
}
In my view I have the following code:
<h2>Recent Posts:</h2>
<ul>
<g:each var="post" in="${returnPosts}">
<li><g:link controller="post" action="show" id="${post.id}">${post.title}</g:link></li>
</g:each>
</ul>
Now, in my controller, I've put in the 'println' statements to ensure that the list is not null, and sure enough it's not. However, when I open the page, the g:each tag doesn't run even once as if the "returnPosts" variable is null, even though in the controller the println statments show that it's not.
I've been going crazy trying to figure this out, can anyone see any reason why the view wouldn't have access to this variable?
You seem to have a controller attribute called 'post' and also your g.each var is 'post'. Potential problem there?
There are couple of things you could do to fix this problem. Firstly, if your view is called index.gsp then you don't need to explicitly call render, returning a list of model objects would do. Your code will look like this:
def index() {
def postList = user.posts
postList.each{ it ->
println "Title: " + it.title
}
[returnPosts: postList]
}
Another thing you could also do is to explicitly import the model object that you are accessing in the view. Not that it matters, but you could try using a name other than post, given that it is a common word. So your gsp will look like this :
<%# page import="com.blah.post" %>
<h2>Recent Posts:</h2>
<ul>
<g:each in="${returnPosts}" var="post">
<li><g:link controller="post" action="show" id="${post.id}">${post.title}</g:link></li>
</g:each>
</ul>
I am trying to list addresses and onChange event I send the address ID and return a list of users.
<g:select name="AddressID" from="${address}" optionKey="id" optionValue="address"
onchange="${ remoteFunction(
action:'testMe',
params:'\'id=\' + this.value' ,
update:'show' )}">
</g:select>
I call this div "show".
<div id="show">
<g:each in="${users}" status="i" var="C">
<h3>${C}</h3>
</g:each>
</div>
However, when I click the item on the list box I get the following error:
description The requested resource (/MyTest/WEB-INF/grails-app/views/test/testMe.jsp) is not available.
My understanding of an update attribute inside a remoteFunction is that it is the name of the div which gets refreshed after the remoteFunction call is compeleted.
Thanks.
I would reorganize your code a little to get the Ajax working:
Move your div contents into a partial template, called, say, _remoteResponse.gsp:
<g:each in="${users}" status="i" var="C">
<h3>${C}</h3>
</g:each>
Modify your controller's testMe action to render the response to a template, something like:
render (template:'remoteResponse', model:[users:['mike,tim']])
Make sure you have an ajax library setup in main.gsp, like:
<g:javascript library="prototype" />
In my Grails controller I'm responding to an AJAX call and using render to return the text:
def ajaxRandomPersonName = {
def person = get a random person ...
render "Name: ${person.name}"
}
The problem is that render renders the whole template. So instead of just rendering "Name: John" it renders all the icons, navigation, etc defined in the template. How do I get render to just render without the template?
I'm pretty much following Chapter 1 of "Grails in Action" (page 28) using Grails 1.1.1.
Follow up:
Returning false per Rhysyngsun's suggestion has no impact. I also tried setting the template to null but it still renders the template:
def ajaxRandomPersonName = {
def person = get a random person ...
render (template:null, text:"Name: ${person.name}")
}
render has its heart bent on rendering it through the template no matter what I do.
Follow up 2: Parallel discussion on grails-user mailing list.
Follow up 3: Sample code:
I paired down my code the bare minimum and it still exhibits the undesired template rendering.
controllers/PersonController.groovy:
class PersonController {
def index = { }
def home = { [message:"Hello"] }
def ajaxTest = {
println "ajaxTest called"
render text: "ajax message"
}
}
views/person/home.gsp (view page for home method)
<html>
<head>
<title>Home View</title>
<g:javascript library="prototype" />
</head>
<body>
<p>
<g:remoteLink action="ajaxTest" update="test1">ajax call</g:remoteLink>
</p>
<p>Message = ${message}</p>
<p id="test1">Blank</p>
</body>
</html>
views/layouts/person.gsp (layout template for person controller)
<html>
<head>
<title>Test App - <g:layoutTitle/></title>
<g:layoutHead/>
</head>
<body>
<h1>Test App</h1>
<g:layoutBody/>
</body>
</html>
I access person controller with the home view:
http://localhost:8080/test/person/home
the page renders as:
Test App
ajax call (hyperlink)
Message = Hello
Blank
"Test App" is from the template. When I click "ajax call" it makes an asynchronous call to PersonController's ajaxTest method (verified with println). All ajaxTest does is println and render static text. This resultant in the following:
Test App
ajax call
Message = Hello
Test App
ajax message
Note that the template is being rendered within "test1" <p> which results in the second "Test App".
I'm running Grails 1.1.1. Any ideas? The code seems straightforward. I downloaded the Grails source and looked at RenderDynamicMethod.java. It doesn't do any template rendering unless template is in the argument list, which it isn't. So my only guess is something up steam is rendering the template again.
Resolved: Adding contentType results in the template not being rendered:
render text: "Name: ${person.name}", contentType: "text/plain"
Make your client side javascript code handle a JSON respond and render your response with:
render [text:"Name: ${person.name}"] as
JSON
You might be getting burnt by the 'layout-by-convention' feature in Grails. If your layout name matches the controller name prefix, for example, Grails will apply the layout to every view managed by that controller. Unfortunately, it even applies to text and templates. There are currently a few JIRAs logged regarding this (see http://jira.grails.org/browse/GRAILS-7624 for example).
I got burnt by this today. I resolved it by simply renaming my layout gsp such that it doesn't match any controller name. My layout was initially named 'storefront.gsp' and I have a controller named StorefrontController. I renamed the layout to 'public.gsp'.
We've found that explicitly returning false from the action fixes this.
I believe doing render foo as JSON returns false implicitly.