I have some common structure that I'd like to use, and I need to nest it within a <g:each />. The semantic solution seems to be to create a taglib, but I'd rather write GSP code to construct the structure, as it's easier to read/maintain.
Essentially, I need this:
<g:each ...>
//Somehow include a GSP that takes parameter "datastructure1"
//Again with "datastructure2"
</g:each>
A GSP include takes params, but it's not nestable in a <g:each />. What am I looking for?
<g:include> works as you need it to. Try again.
You can call a taglib, then in the taglib function: render a template. There's an example here.
Related
Is it possible to create a custom GSP tag without writing Groovy code and embedding my HTML in the code (i.e. more of a JSP style way of creating a custom tag)?
I have a menu that consists of a bunch of items something like:
<li class="menu-item">
<g:link controller="someController" action="someAction" id="123">
My Item Text
</g:link>
</li>
I would like to create a new GSP tag to simplify my pages since it will be repeated multiple times. So, I'd like to create something like:
<my:menuitem controller="someController" action="someAction" id="123" text="My Item Text"/>
I know that I can create a custom taglib and create the tag using Groovy code. However I really don't like the idea of embedding HTML into a Groovy file. In the past I have created JSP taglibs in essentially a JSP file without writing Java code. So far looking at the documentation for Grails I haven't seen a similar style.
As a side note, can custom JSP tags be used within GSP?
You can do this with a template via the render tag, as explained in the "Views and Templates" section of the docs. Its worth noting you name the template file with a leading underscore but you refer to it in the render tag without the underscore.
The other alternative is to use a custom taglib as you described but to create your HTML with the Groovy MarkupBuilder. It takes a bit of getting used to (syntax is a bit strange) but once you've done a few times it becomes second nature.
The only way I can see to do what you want to do without a Taglib is to use g:render and pass in your values into the model attribute. Like this:
<g:render template="myTemplate" model="[controller: 'someController', action: 'someAction', id: 123, text: 'My Text Item']" />
Then in your actual template you will have the following:
<li class="menu-item">
<g:link controller="${controller}" action="${action}" id="${id}">
${text}
</g:link>
</li>
So my question is, hopefully, very simple.
I have two different domains with corresponding controllers/view folders etc.
I want to call the second _form.gsp from the first _form.gsp (within a g:each as there will be multiple things to display) and pass in the relevant data for the second _form.gsp to render from, how do I do that?
I know I can use g:render template = "myotherForm" but I don't know how to point it to another view folder or how to pass in the details...
Thanks in advance and let me know if more information is required...
You can Refer this
Grails uses the convention of placing underscore before the name of a view to identify it as a template.
Example grails-app/views/book/_bookTemplate.gsp:
<div class="book" id="${book?.id}">
<div>Title: ${book?.title}</div>
<div>Author: ${book?.author?.name}</div>
</div>
Then use render tag
<g:render template="bookTemplate" model="[book: myBook]" />
You're right, <g:render is the right tool. By default, for template="myOtherTempalte" it looks for tempalte in current directory, but you could pass full path, if it's from another controller. Like template="/forms/myOtherTemplate". And use model="" to pass parameters, same as inside controller:
<g:each in="${things}" var="x">
<g:render template="/forms/myOtherTemplate" model="${thing: x}"/>
</g:each>
I'm working with a template that looks like this
<g:render template="templateName" model="[t:t, s:s, domainClass: domainInstance]"/>
I'm not sure of the terminology I should use but the above "domainInstance" needs to be replaced with something in the order of
${Adomainclass.list([max:1])}
I've tried surrounding it with single quotes and various other things I can't figure out how to satisfy the model.
Any tips here?
Dollar-currly-braces should be in the beginning of the model definition.
<g:render template="templateName" model="${[t:t, s:s, domainClass: Adomainclass.list([max:1])]}"/>
I believe you are missing import statement in gsp:
<%#page import="Adomainclass"%>
<g:set var="instances" value="${Adomainclass.list([max:1])}" />
<g:render template="templateName" model="['t':t, 's':s, 'domainClass':instances]"/>
I am using the Dojo plugin for Grails to populate a dojox.grid.DataGrid object. Right now my controller action associated with this grid renders the JSON that defines the grid contents. That works just fine as long as I predefine the columns in the GSP. However, my application needs to be able to set the number of columns (and their associated names) dynamically based on some database query results. The JSON format for this grid does not include the column names so I cannot use a g:each tag in my GSP to iterate through the names.
I wanted to do something like this but am unable to do so:
<dojo:grid controller='foo' action='getGridData' ...>
<g:each in=${columns}>
<dojo:col width="15%" name="{it}" field="{it}">{row.{it}}<dojo:col/>
</g:each>
</dojo:grid>
I gave the specific example of the Dojo plugin for background but I would like to extend this to a more general question about Grails. If I am constructing a GSP element by a controller action that renders JSON how do I access other things in the controller for the construction of nested elements? Is this even possible? I am still new to web development so I am sure I am misunderstanding some of the glue between these components.
The main thing I see wrong with your code is you're trying to reference the columns data incorrectly.
<g:each in="${columns}">
<dojo:col width="15%" name="${it}" field="${it}">{row.{it}}<dojo:col/>
</g:each>
Note the quotes around the in= value and the dollar sign used to reference the it variable.
Regarding the last bit
{row.{it}}
I'm unclear on what row is in this case. So I'm not sure how that needs to be fixed, but maybe this gets you moving in the right direction.
You generally don't render a GSP and construct JSON in one request. What will happen here is you render your GSP which takes all your taglib code and produces HTML/JavaScript. Then, once the browser renders it, an AJAX call takes place to fetch the JSON.
Remember that by the time the GSP reaches the browser, it is just HTML.
I have a g:select statement that looks like the following:
<g:select id="gearbox" name="gearbox.id" from="${com.nppc.mes.energyusage.Gearbox.list()}" optionKey="id" optionValue="${ {"${it.gearboxType} - (${it.gearboxRatio})"} }" required="" value="${gearboxVoltageInstance?.gearbox?.id}" class="many-to-one"/>
I have added an optionValue attribute: optionValue="${ {"${it.gearboxType} - (${it.gearboxRatio})"} }"
This works as I want.
However, I want to show my domain object, Gearboxes the same everywhere. I have created a template, and am able to use the g:render tag on my show.gsp.
What I can't figure out is how to get something like this to work:
optionValue="<g:render template="/shared/gearbox" model:="[gearbox:it]"/>"
Is it possible to use templates to generate the content that goes into an optionValue?
You could hack around it, but it feels like bad design to me.
The right way to do something like is seems to be to add a helper method to your Gearbox domain class
static transients = [ 'renderedValue' ]
def getRenderedValue(){
"$gearboxType - $gearboxRatio"
}
Then, you can just call optionValue="${ it.renderedValue }".
Also, if you specify a toString() in your domain class, this would be used to generate the default rendered value.
Tags can be used as regular functions in Groovy code. Like:
optionValue="${g.render(template: '/shared/gearbox', model: [gearbox: it])}"