execute GORM query in GSP with Grails - grails

In my gsp I have to execute queries to get back some datas. My queries work in a controller, and the same ones do not work in my gsp. I suppose this is because of the quotes, and I've tried to escape quotes, without success.
Here is my actual code :
<%# page import="package.PositionnementProfil" %>
<html>
<g:set var="listPositionnementActuel" value="${PositionnementProfil.executeQuery("from PositionnementProfil as pp WHERE pp.profil = ':profilInstance' AND pp.positionnement.libelle = 'possible'", [profilInstance:profilInstance])}" />
[...]
</html>
<body>
<g:each in="${listPositionnementActuel}" var="pos" >
<h1>test</h1>
</g:each>
[...]
</body>
which prints nothing. If I do a simple PositionnementProfil.list() I've got all the results

Related

how to correctly render controller output to GSP

in my grails application, I have a controller that reads a directory and returns a list of files in it.
My issue is that in my GSP (view) it is not matching the out put from the controller.
Here is my controller:
package frametest
import groovy.io.FileType
class Read_dirController {
def index() {
def list = []
def dir = new File("D:\\TestRepoLocal\\APIAutomation\\src\\test\\cucumber\\features")
dir.eachFileRecurse (FileType.FILES) { file ->
list << file
}
list.each {
println it.name
}
def found = []
dir.eachFileMatch(FileType.ANY, ~/.feature/) {
found << it.name
}
render(view: "index", model: [name:name])
}
}
here is my GSP (view):
<%# page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<meta name="layout" content="main"/>
<title>Welcome to The Marriot test Page</title>
</head>
<body>
<div class="body">
<h2>Marriott Automation Test Page</h2>
<br>
<p></p>
<h3>This is where we can launch our tests and get reports</h3>
<br>
<br>
<p></p>
${name}
</div>
</body>
</html>
The output should just list the file names. It does in the controller output (shown in console), but in the view it shows this:
[D:\TestRepoLocal\APIAutomation\src\test\cucumber\features\APIWAL_525_Account_Security_otp.feature, D:\TestRepoLocal\APIAutomation\src\test\cucumber\features\AssignRoomToReservation.feature, D:\TestRepoLocal\APIAutomation\src\test\cucumber\features\DeleteAccount.feature, D:\TestRepoLocal\APIAutomation\src\test\cucumber\features\DeleteConsumersPaymentMethods.feature, D:\TestRepoLocal\APIAutomation\src\test\cucumber\features\GetActivitiesByID.feature, D:\TestRepoLocal\APIAutomation\src\test\cucumber\features\GetAddressType.feature, D:\TestRepoLocal\APIAutomation\src\test\cucumber\features\GetAddrMiscType.feature, D:\TestRepo
Local\APIAutomation\src\test\cucumber\features\GetAlerts.feature,
the console output for the controller shows this:
APIWAL_525_Account_Security_otp.feature
AssignRoomToReservation.feature
DeleteAccount.feature
DeleteConsumersPaymentMethods.feature
GetActivitiesByID.feature
GetAddressType.feature
GetAddrMiscType.feature
GetAlerts.feature
GetAttractionsByID.feature
What do i need to do to make the view match the controller output from console??
thanks!
ironmantis7x
UPDATE!!!!!
to solve my listing issue I did this:
I changed the controller file to do this little trick:
render(view: "index", model: [name:list.name])
then to make the gsp list the file names on a new line, I did this:
<ul>
<g:each in="${name}" var="fileName">
${fileName}<br>
</g:each>
</ul>
And presto!!
This is where we can launch our tests and get reports
APIWAL_525_Account_Security_otp.feature
AssignRoomToReservation.feature
DeleteAccount.feature
DeleteConsumersPaymentMethods.feature
GetActivitiesByID.feature
GetAddressType.feature
GetAddrMiscType.feature
.....
Thanks guys for encouraging me to struggle to learn it and helping me along the way!
Your gsp is rendering the list but your list of names is in the variable found, not name. Anyway, your last action line should be:
render(view: "index", model: [name: found])
In other hand, your gsp is rendering the list, but should give it some style. An example:
<ul>
<g:each in="${name}" var="fileName">
<li>${fileName}</li>
</g:each>
</ul>
You are storing your o/p in field named found, but in model you are using field name to be included as name, which doesn't contain your o/p. You haven't declared name, or have added anything to it, idk how it is showing that o/p even on gsp.

Methods in service doesn't work ok in the gsp file

I have a list with two buttons and I want that everytime that I press a button, work the code that I have associated to this button. This code is in a service, and the gsp file is a default list.gsp
To call the service from the gsp. I took this post:(How do I call a Grails service from a gsp?) to do it.
The problem is that I have two methods in the service and I don't know why, but always that I enter in the list.gsp and always that I press the button I can see display in the console of grails that the two methods are working at the same time.
This is that I can see in the console everytime I push button A or B:
2015-12-01 12:51:47,565 [http-bio-8090-exec-5]
hello
world
That I want is that if I press button A show this:
2015-12-01 12:51:47,565 [http-bio-8090-exec-5]
hello
and if I press button B show this:
2015-12-01 12:51:47,565 [http-bio-8090-exec-5]
world
And this is that I can see in the console everytime that I run and enter in the gsp.file and I want that don't run the code unless I press the button:
2015-12-01 12:51:47,565 [http-bio-8090-exec-5]
hello
world
Thanks in advance
This is my code in gsp:
<%# page import="com.app.test" %>
<%# page import="mypackage.myService" %>
<!DOCTYPE html>
<html>
<head>
<meta name="layout" content="main">
<g:set var="entityName" value="${message(code: 'licenseType.label', default: 'LicenceType')}" />
<title><g:message code="default.list.label" args="[entityName]" /></title>
</head>
<body>
<g:message code="default.link.skip.label" default="Skip to content…"/>
<div class="nav" role="navigation">
<ul>
<li><g:link class="create" action="create"><g:message code="default.new.label" args="[entityName]" /></g:link></li>
<% def LicenceTypeService =
grailsApplication.classLoader.loadClass('mypackage.myService').newInstance()%>
<li><g:link action="list"><g:message code="Calculate Licence Type" args="[entityName]" /><span>${myService.calculate()}</span></g:link></li>
<li><g:link action="list"><g:message code="Re-Calculate Licence Type" args="[entityName]" /><span>${myService.recalculate()}</span></g:link></li>
</ul>
</div>
In the service:
class MyService {
def calculate(){
println "hello"
}
def recalculate(VoiceUser vUser){
println "world"
}
}
I'm fairly certain this is impossible; what you are asking is to send an Ajax call directly to a grails service. If you think about it, once the generated HTML has been received by the client, there is not a direct connection between the browser and back-end (grails application) so there can't be any grails magic that allows this to happen.
There is a grails tag g:remoteLink that will allow Ajax calls to a controller action, the controller is necessary at this point because all new interactions once the generated html is in place must be through standard HTTP requests and requests are handled through grails controllers.
Your best bet would be to create a controller that wraps the 2 service methods and use the actions with g:remoteLink or another Ajax request.
As to using a service within a gsp, instead of instantiating a new service, I would argue in favor of using the existing spring bean.
Replace:
<%# page import="mypackage.myService" %>
...
<% def LicenceTypeService = grailsApplication.classLoader.loadClass('mypackage.myService').newInstance()%>
With:
<g:set var="myService" bean="myService"/>

Simple Hello World Grails Form Submission

I am new to Grails and I am trying to get a very simple example to work. I should just submit a form and display "Hello World" on the screen. It consists of the following controller:
package surface
class SearchController {
def index() {
render(view: "search")
}
def result() {
render "Hello World"
}
}
and a view, with the form:
<%# page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<g:form name="searchform" url="result">
<g:textArea cols="80" rows="30" name="searchfield"/>
<g:actionSubmit value="Ask"/>
</g:form>
</body>
</html>
When I click on "Ask" I get a 404 error but the browser correctly accesses "/surface/search/result". When I enter that address directly without using the form the "Hello World" appears correctly. This is probably a no-brainer but I seem to be unable to find out why this does not work from the documentation.
Complementing the #Tom Metz answer, what you need to keep in mind in the Grails controller structure is that every public method is considered an action. This action is mapped to a url. In your example will exists /search/index and /search/result (controller + action).
The documentation of the g.form is corret, since this says that;
url (optional) - A map containing the action,controller,id etc.
So to correct your view you can set the action as commented or you can adjust the way you use url:
<g:form name="myForm" url="[action:'result',controller:'search']">

Grails g:include can it be done?

Im wondering if it is possible to use g:include to include only the body contents of a given page.
Say i have a main layout page as follows:
<html>
<head>
<title>My start page</title>
<g:layoutHead>
</head>
<body>
<g:layoutBody>
</body>
</html>
Then a main page (index.gsp)
<html>
<head>
<!-- main layout reference -->
<meta name="layout" content="main"/>
</head>
<body>
THIS IS MY INDEX BODY CONTENT WITH AN INCLUDE
<g:include controller="book" action="list"/>
<g:link controller="book" action="list">See the full list!</g:link>
</body>
</html>
And finally the book/list page
<html>
<head>
<!-- main layout reference -->
<meta name="layout" content="main"/>
</head>
<body>
<table>
<g:each in="${books}">
<tr>
<td>${it.author}</td>
<td>${it.title}</td>
<td>${it.price}</td>
</tr>
</g:each>
</table>
</body>
</html>
So what i want to achieve is that the main page (index.gsp) only includes the table defined in the book/list page. However, when i try this it includes the entire html defined (<html> tags and all).
is it possible to do this somehow? i've tried things like <g:include controller="book" action="list" view="someView.gsp"/> however this doesn't work. I really want to avoid having to add a book list logic to the "index controller" i want to reuse my existing controller.
I can't be the first person out there having this usecase, what solutions have you guys come up with?
You can use the applyLayout tag. Simply create an empty.gsp layout with only:
<g:layoutBody/>
And then decorate your include tag with applyLayout:
<g:applyLayout name="empty">
<g:include controller="book" action="list"/>
</g:applyLayout>
See the entry on the Grails guide for further reference.
This is IMHO directly not possible. An idea would be to create a custom tag based on g:include, that strips out parts of the code by e.g. an xpath expression. I'm not aware that this already exists somewhere.
An alternative would be to refactor the body part of book's list.gsp into a template and reference that template from index.gsp using g:render. But this means that the data model has to be available in index.gsp context since g:render does not invoke a controller.
Side note: when using g:include it's a good idea to use the springcache plugin for page fragment caching.
Yes, but you need you need one more level in there. Look at Grails templates. Essentially, you'd have a template: _books.gsp containing:
<table>
<g:each in="${books}">
<tr>
<td>${it.author}</td>
<td>${it.title}</td>
<td>${it.price}</td>
</tr>
</g:each>
</table>
Then your index would be:
<html>
<head>
<!-- main layout reference -->
<meta name="layout" content="main"/>
</head>
<body>
THIS IS MY INDEX BODY CONTENT WITH AN INCLUDE
<g:render template="books">
<g:link controller="book" action="list">See the full list!</g:link>
</body>
</html>
And your list would be:
<html>
<head>
<!-- main layout reference -->
<meta name="layout" content="main"/>
</head>
<body>
<g:render template="books" />
</body>
</html>
(My syntax may not be 100% right, since it's been a couple months since I've done this, but the idea behind templates are short, reusable pieces of GSP code that aren't meant to be displayed on their own.

How do I pass a variable into grails template from a Layout file?

So I have a navigation template (/common/_navigation.gsp) that is getting rendered in the Grails projects main Layout file (/layouts/main.gsp). How do I pass some kind of variable/parameter/arg from the individual view files to layout and eventually into the navigation template? I just want the right tab to be highlighted when I'm on a page.
(We've already tried using the Grails Navigation Plugin. Since we have different tabs that point to the same controllers (same view, different filter) it breaks down.)
I do this pattern all the time. In my view, I can attach a property to the page either manually or by using the parameter tag in the view that I'm rendering. Its not documented in the Grails user guide, but its super handy.
<parameter name="foo" value="bar" />
Then I would access the page property by using the pageProperty tag.
<g:set var="activeNavItem" value="${pageProperty(name: 'page.foo')}"/>
The layout doesn't need to handle this variable at all :-)
just use the model parameter
for Example:
view:
<g:render template="../path/template" model="[header:'test', headers:['a','b'], values:[['a':1,'b':2],['a':3,'b':4]] ]"/>
_template:
<br/>
<h3>${header}</h3>
<table>
<thead>
<tr>
<g:each in ="${headers}" var="he">
<th>${he}</th>
</g:each>
</tr>
</thead>
<tbody>
<g:each in ="${values}" var="v">
<tr>
<g:each in ="${headers}" var="h">
<td>${v[h]}</td>
</g:each>
</tr>
</g:each>
</tbody>
</table>
I use an arguably simpler method. Just define a variable at request scope in the individual view before you call your layout. It will be available in all templates used in the request, including the layout and any called via <g:render>
<g:set var="SOMEVARIABLE" value="SOMEVALUE" scope="request"/>
<meta name="layout" content="yourlayout">
Then just reference the variable as you would any other in your layout or other templates pulled in by your view
${SOMEVARIABLE} or <g:if test="${SOMEVARIABLE}">, etc., etc
You'd need to use a page property: http://grails.org/doc/1.1.1/ref/Tags/pageProperty.html
Then pass it into the render tag using the model param.
cheers
Lee
The pattern I like, uses the pageProperty as follows. In the layout, I reference the pageProperty like so:
The layout gsp
<body id="${pageProperty(name: 'page.pageType')}">
<g:render template="/layouts/header" />
<g:layoutBody/>
<g:render template="/layouts/copyright" />
</div>
... and within the <head> section of the specific gsp page (I found that it did NOT work outside the head section), I declare the value like so:
The page gsp
<head>
<meta name="layout" content="main"/>
<parameter name="pageType" value="homePg" />
</head>
Resulting HTML
<body id="homePg">
... header, body and footer ...
</body>
In addition, I can inject a value from the controller model into pageProperty like so:
Controller
def index() {
model: [modelPageType: 'adminPg']
}
The layout gsp (using the same layout as above)
<body id="${pageProperty(name: 'page.pageType')}">
<g:render template="/layouts/header" />
<g:layoutBody/>
<g:render template="/layouts/copyright" />
</div>
The page gsp
<head>
<meta name="layout" content="main"/>
<parameter name="pageType" value="${modelPageType}" />
</head>
Resulting HTML
<body id="adminPg">
... header, body and footer ...
</body>
You can simply reach any variable in any template in the page by getting it from params.
Just type ${params.variable} in layout and you will get your variable.
Based on my readings, I think its not a good practice to pass variables to your layout. Model variables are accessible in your view. I think layouts should be used only to specify the structure of the page while views can be used to fill in the content.

Resources