I have a domain
class Node {
String nodeId
String label
Node parent
}
In the GSP page I want to start with the root and print all its children (note I have a reference to parent and not the child). Any idea how to do this ?
I am sorry but I am new and really confused. I want to print everything going down from root(not root) and root has no parent(its null). So i have written
<g:each in="${nodes}" var="node">
<g:if test="${node.parent!=null}">
${node.label}
<g:render template="node" model="[nodes:Node.findAllByParent(node)]" />
</g:if>
</g:each>
In the above code not sure what parent_node_intance should be. The nodes list starts with root. I dont want to print that but start from everything else that has root as parent.
node.gsp
<g:if test="${nodes}">
<ul>
<g:each in="${nodes}" var="node">
<li>
${node.label}
<g:render template="node" model="[nodes:Node.findAllByParent(node)]" />
</li>
</g:each>
</ul>
</g:if>
Getting the following error which I am sure is caused by the root
2014-10-02 12:28:21,693 [http-bio-8080-exec-1] ERROR errors.GrailsExceptionResolver - NullPointerException occurred when processing request: [GET] /taxonomy - parameters:
outputFormat: concept
hierarchyId: lp
Cannot invoke method findAllByParent() on null object. Stacktrace follows:
Message: Error evaluating expression [[nodes:Node.findAllByParent(node)]] on line [11]: Cannot invoke method findAllByParent() on null object
Line | Method
->> 11 | run in C:/Users/U6021072/Documents/workspace-ggts-3.6.0.RELEASE/ae-and-sdx-analysis-ui/target/work/plugins/taxonomy-toolkit-for-grails-0.02-SNAPSHOT/grails-app/views/taxonomy/concept.gsp
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Caused by NullPointerException: Cannot invoke method findAllByParent() on null object
->> 11 | doCall in C__Users_U6021072_Documents_workspace_ggts_3_6_0_RELEASE_ae_and_sdx_analysis_ui_target_work_plugins_taxonomy_toolkit_for_grails_0_02_SNAPSHOT_grails_app_views_taxonomy_concept_gsp$_run_closure4
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 198 | doFilter in grails.plugin.cache.web.filter.PageFragmentCachingFilter
| 63 | doFilter in grails.plugin.cache.web.filter.AbstractFilter
| 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 615 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^ 745 | run in java.lang.Thread
So, you want to print all the nodes that have the known parent?
What about something like:
<g:each in="${Node.findAllByParent(parent_node_instance)}" var="node">
${node}<br>
</g:each>
But since you are talking about recursion, I think you also want to print all descendants.
Create a _node.gsp template:
<g:each in="${nodes}" var="node">
${node}<br>
<g:render template="node" model="[nodes:Node.findAllByParent(node)]" />
</g:each>
And call with:
<g:render template="node" model="[nodes:Node.findAllByParent(parent_node_instance)]" />
You can easily add a depth variable to the model to indent each generation properly, or use the <ul> and <li> elements in the template.
parent_node_instance is the root you want to start printing your tree from, it can be the absolute root or any node in the tree.
findAllByParent() is a dynamic finder function. See http://grails.org/doc/latest/guide/GORM.html#finders for details.
you can also use the #collection/#bean:
_node.gsp
<div class="fancy nested">
id:${it.nodeId} - label:${it.label}
<g:render template="node" collection="${Node.findAllByParent(it.node)}" />
</div>
main.gsp
<g:render template="node" bean="${rootNode}" />
Related
I got this error when I wanted to add another menu to my drop-down menu.
I am not sure why this error came up.
I added dropdown.avatar. because that what other menus also had. But it didn't work. What could I be missing here?
circle CI said it's a 33:41 error Parsing error: Unexpected token
31 | <Link route="/stats">
32 | <a>
> 33 | <Icon type="profile" /> {{t("dropdown.avatar.viewMoreStats")}}
| ^
34 | </a>
35 | </Link>
36 | </li>
I have a controller which is passing on a hashmap to a view. The map has 3 elements, one of which is as below:
-- A list of lists (A) in which list3 is a list of lists
Now I want to display them on the gsp as follows:
-----------------------------------------------------------------------------
A.list1 | A.list2 | A.list3[0] | A.list4 |
| | A.list3[1] | |
| | A.list3[2] | |
----------------------------------------------------------------------------
I have very little knowledge about generating views and I need nothing more than the tabular format here. Nothing more fancy. I just want the table because the data makes sense only in that format. Thank you.
welcome to the Grails world. Hope you have an awesome experience. Unsure if you are aware but by generating a view i.e. the default scaffolding CRUD elements auto generated and most specifically the list.gsp has most of that logic in place. None the less I reviewed your question over again and can see your stuck on map that has a list which is really simply stuff. So here goes.:
<g:each in="${A}" var="myMap">
<tr>
<td>${myMap.list1}</td>
<td>${myMap.list2}</td>
<td>
<g:each in="${myMap.list3}" status="i" var="myList3">
${myList3} <!-- this should be what you want I have added below -->
<!-- ${myList3?.name} --> <!-- explained further below -->
<!-- ${i} : ${myList3} --> <!--where i is this is the iterator -->
</g:each>
</td>
<td>${myMap.list4}</td>
</tr>
</g:each>
I put in comments myList3?.name simply because if the list is actually a binding of domain objects then you could display the element from the domainclass that is that being returned.
so:
class Country {
String name
static hasMany=[cities:Cities]
}
Class Cities {
String name
static belongsTo=[Country:country]
}
Then if A was ${country} and list3 was cities then .name would actually show the cities.name which is the binded value...
In other examples of raw maps that are not domainClass binded being returned to a gsp you could use the key value definition to parse:
raw map being passed to gsp
private Map menuMap = ['index':'Socket method', 'ajaxpoll':'Ajax poll',
'socketremote':'RemoteForm Websocket', 'scsocket':'NEW: Websocket Client/Server']
navbar gsp
<g:each in="${menuMap }" var="cmenu">
<li <g:if test="${actionName == cmenu.key}">class="active"</g:if>>
<g:link action="${cmenu.key}">
${cmenu.value}
</g:link>
</li>
</g:each>
I'm trying to create a mobile application with JQuery Mobile that is responsive design.
In other words, I want, in smartphone, that "page1.html" and "page2.html" are loaded in separed pages like that :
_________ __________
|Page1 | |Page2 |
|.html | on click |.html |
| | <--------- | |
| | |go to |
|go to | on click |page1 btn|
|page2 btn| ----------> | |
|_________| |_________|
And, in tablets, I want that page1.html and page2.html are loaded in the same page like that :
-----------------------------
|Page1.html | Page2.html |
| |
| |
| |
| |
| |
|----------------------------
How to do that with JQueryMobile ? I have try to $.mobile.loadpage(url) and $.mobile.changepage(url) but the problem is that the page is replaced and I need to have two pages in a single view for tablets.
Thanks per advance for your help.
Its simple enough, like #Omar said, first of all use a single page template like this with 'data-role=page' denoting each page.
<body>
<div data-role="page" data-theme="d" id="pageOne">
<---header---->
<--- content --->
<---footer---->
</div>
<div data-role="page" data-theme="d" id="pageTwo">
<---header---->
<--- content --->
<---footer---->
</div>
Now, Jquery mobile will automatically show 'pageOne' on first load and hide 'pageTwo' and on navigating to 'pagetwo' will hide 'pageOne'.
After this you can write a css media query similar to this:
#media all and (min-width: 450px) {
#pageOne{
display:block;
float: left;
width:50%;
postion:relative;
}
#pagetwo{
display:inline-block;
float:right;
width:50%;
padding-left: 2em;
postion:relative;
}
}
So if any with width greater than the mentioned width(450px) will have both the pages displayed side by side. Hope this helps. Here is a simple working sample I made.
http://jsfiddle.net/uwZpM/
I have this:
<!-- <div class="fieldcontain ${hasErrors(bean: azafataInstance, field: 'localidad', 'error')} required" style="margin-left: 10px">-->
<!--<label for="localidad">Localidad</label> -->
<!--<g:if test="${params?.localidad }">-->
<!--<g:select id="localidad" title="${g.message(code: 'infoPersonal.localidad')}" name="localidad" value="${params?.localidad}" from="${[' ',params.localidad]}" noSelection="${['':message(code:'localidadSelect')]}" onClick="this.style.color='black'" onFocus="this.style.color='black'" style="max-width:168px" />-->
<!--</g:if>-->
<!--<g:else>-->
<!--<g:select id="localidad" title="${g.message(code: 'infoPersonal.localidad')}" name="localidad" value="${params?.localidad}" from="${['']}" noSelection="${['':message(code:'localidadSelect')]}" onClick="this.style.color='black'" onFocus="this.style.color='black'" style="max-width:168px" />-->
<!--</g:else>-->
<!--</div>-->
As you can see... lines are commented. I run the project and i got this:
URI
/com.publidirecta.azafatas/azafataCertificada/registro_page
Class
org.codehaus.groovy.grails.web.taglib.exceptions.GrailsTagException
Message
Tag [else] cannot have non-whitespace characters directly preceding it.
Around line 95 of grails-app/views/azafataCertificada/registro.gsp
92:<!--<g:if test="${params?.localidad }">-->
93:<!--<g:select id="localidad" title="${g.message(code: 'infoPersonal.localidad')}" name="localidad" value="${params?.localidad}" from="${[' ',params.localidad]}" noSelection="${['':message(code:'localidadSelect')]}" onClick="this.style.color='black'" onFocus="this.style.color='black'" style="max-width:168px" />-->
94: <!--</g:if>-->
95: <!--<g:else>-->
96: <!--<g:select id="localidad" title="${g.message(code: 'infoPersonal.localidad')}" name="localidad" value="${params?.localidad}" from="${['']}" noSelection="${['':message(code:'localidadSelect')]}" onClick="this.style.color='black'" onFocus="this.style.color='black'" style="max-width:168px" />-->
97:<!--</g:else>-->
98:<!--</div>-->
Trace
Line | Method
->> 886 | runTask in java.util.concurrent.ThreadPoolExecutor$Worker
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 908 | run in ''
^ 680 | run . . in java.lang.Thread
Caused by GrailsTagException: Tag [else] cannot have non-whitespace characters directly preceding it.
->> 95 | runTask in /grails-app/views/azafataCertificada/registro.gsp
The question is, obviously...
How is it possible, in a decent framework, can a commented line throw an exception!!!
Because <!-- isn't a comment in GSP.
As you have discovered, the GSP parser treats HTML-style comments as normal content, to make it possible to generate output that contains HTML comments such as within script tags
<script type="text/javascript><!--
js goes here;
//--></script>
or IE conditional comments
<!--[if IE 6]>
<script type="text/javascript" src="${resource(dir:'css', file:'ie6-fixup.js')}"></script>
<![endif]-->
The syntax for GSP comments is
<%-- this is commented out --%>
the GSP parser will ignore anything inside this sort of comment.
I'm trying to add a static block (which is actually a text link) after my site's home page only, by using the Layout update XML box on the CMS pages interface.
--------------
| |
| Content |
| |
---------------
| Footer |
| Copyright |
---------------
| My Block |
---------------
I've tried adding the block using this code:
<reference name="footer">
<block type="cms/block" name="credits" after="-">
<action method="setBlockId"><block_id>my_block</block_id></action>
</block>
</reference>
The problem is: #1 that my block shows between the Footer and Copyright and #2: the change is visible on all the pages, whereas I only want it to show on my home page and not in the rest of the site...
Note: I'm running a Magento 1.4.0.1
In order to display it only at your home page you have to add your XML under <cms_index_index>.
To adjust positioning use <?php echo $this->getChildHtml('credits') ?> inside of your page/html/footer.phtml.