Render a Map of lists as a table in grails - grails

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>

Related

Grails gsp: count of auto-number in list

How do I get a count (auto-number) inside of an each loop in a gsp (groovy server page)? I'm doing a project of FAQ's. The following code works just fine, but I'd would like to number each question in the output like:
FAQ question here...
Answer here....
2, FAQ question here...
Answer here....
<g:each in="${gFaqCategory.list()}" var="faqCategory">
<p><b>${faqCategory.categoryType}</b></p>
<g:each in="${Faq.findAllByFaqCategory(faqCategory)}" var="faq">
<li><p>${faq.question}</p></li>
<li><p>${faq.answer} </li></p>
</g:each>
</g:each>
<g:each in="${Faq.findAllByFaqCategory(faqCategory)}" var="faq" status="i">
<li><p>${i+1}. ${faq.question}</p></li>
<li><p>${faq.answer} </li></p>
</g:each>
Use status in g:each. Strongly suggest to go through the doc.

Counters in Loops in Thymeleaf

Is there a way to do a loop in Thymeleaf without a list?
I'd like to essentially convert this snippet to Thymeleaf:
<jsp:useBean id="now" class="java.util.Date" />
<fmt:formatDate var="year" value="${now}" pattern="yyyy" />
<c:forEach var="i" begin="0" end="99">
<form:option value="${year-i}" />
</c:forEach>
</form:select>
-- Update --
I've decided this is along the lines of how I want to do it, but I'm not sure about the springEL syntax:
<option th:each="i : ${#numbers.sequence( 1, 100)}" th:value="#{ T(java.util.Date).getYear() - $i }">1</option>
In case you are still looking for the correct SpEL syntax,
here's what worked for me:
<option th:each="i : ${#numbers.sequence( 1, 100)}"
th:value="${ (new org.joda.time.DateTime()).getYear() - i }"
th:text="${ (new org.joda.time.DateTime()).getYear() - i }">1</option>
Notice:
added th:text to set the option text.
used Joda-Time instead as java.util.Date wouldn't give me the desired outcome
Read this discussion on java.util.Date and getYear()
You can use the special thymleaf iteration variable inside the each block.
This special variable name is the name of your element variable concatenate with the keyword 'Stat' (ex: elt -> eltStat)
This variable gives you many information related to the iteration.
You can also specify this variable name after your element variable. For example:
<tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? 'odd'">
<td th:text="${prod.name}">Onions</td>
<td th:text="${prod.price}">2.41</td>
<td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>
More information in the official documentation below:
http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#keeping-iteration-status

Struts2 passing url parameter to sort tag

I´m newbie to Struts FW and JSP at all. I have a couple of list rows generated through <s: iterator>. I wanted to get this list sorted according to each column (name, address, etc.)
so I added <s:sort> tag and created to comparator classes (name, address).
Now, I wonder how can I pass through the URL parameter which type of comparator I want to use?
The code looks like this:
<s:bean name="ois.AlphabetComparator" var="alphabetComparator" />
<s:bean name="ois.AddressComparator" var="addressComparator" />
<s:url id="place" action="getAllPlaces">
<s:param name="sortStyle">#addressComparator
</s:param>
</s:url>
<s:a href="%{place}">
<s:sort comparator="?how to pass url parameter here?" source="places">
<s:iterator status="status">
...
</s:iterator>
</s:sort>
EXAMPLE 1
Use #parameters['sortStyle'] to obtain the value of the parameter. First create URLs with distinct values for the parameter sortStyle :
<s:url id="place_sortByAddress" action="getAllPlaces">
<s:param name="sortStyle">ois.AddressComparator
</s:param>
</s:url>
<s:url id="place_sortByAlphabet" action="getAllPlaces">
<s:param name="sortStyle">ois.AlphabetComparator
</s:param>
</s:url>
Then add links (assuming the goal is to sort the list in various ways depending on the selected link) :
<s:a href="%{place_sortByAddress}">Sort by Adress</s:a></br>
<s:a href="%{place_sortByAlphabet}">Sort by Alphabet</s:a></br>
The next step is a little more tricky. If there is actually a parameter called sortStyle, then a new bean is created from the value of the parameter sortStyle. This bean will be the comparator class to sort items in the list.
<table>
<tbody>
<s:if test='%{#parameters["sortStyle"] != null}'>
<s:bean name='%{#parameters["sortStyle"]}' var="comparatorClass" />
<s:sort comparator="#comparatorClass" source="places">
<s:iterator>
<tr>
<td><s:property value="name"/></td>
<td><s:property value="adress"/></td>
</tr>
</s:iterator>
</s:sort>
</s:if>
</tbody>
</table>
For example, if you clicked on the first link, your comparator class would be ois.AddressComparator.
This solution should work fine, but it relies on the use of the parameter, that the user can see and modify, and that we must also check directly in the jsp with a "if" tag.
Checks and changes could be handled on server-side by the Action class. It may be improved thanks to struts.
EXAMPLE 2
in the JSP, use struts s:form tag. Create submit buttons for this form with s:submit tags. Each submit button calls a different method of the Action class, one for each way to sort the list.
<s:form action="getAllPlaces">
<!-- Submit buttons -->
<s:submit key="messages.submit" action="getAllPlaces" method="sortByAdress"/>
<s:submit key="messages.submit" action="getAllPlaces" method="sortByAlphabet"/>
Then create a table for displaying items of the list. As in the first example, a bean is created from a parametric value. Instead of a parameter sent in the URL, an attribute is set by the Action class and is used in the JSP. Let the Action class handle controls and changes on this attribute.
<!-- Table for list -->
<table>
<tbody>
<!-- Create a new bean with parametric class name -->
<s:bean name="%{#attr['comparatorClassName']}" var="comparatorClass" />
<s:sort comparator="#comparatorClass" source="places">
<s:iterator>
<tr>
<td><s:property value="name"/></td>
<td><s:property value="adress"/></td>
</tr>
</s:iterator>
</s:sort>
</tbody>
</table>
</s:form>
There, is the code from the Action class. It has a comparatorClassName attribute with a default value. The value changes each time you call for methods sortByAlphabet() or sortByAddress.
public class GetAllPlacesAction extends ActionSupport{
/**
*
* #return
*/
private List<PlaceBean> places = new ArrayList<PlaceBean>();
// Set default comparator class name
private String comparatorClassName = "ois.AlphabetComparator";
public String execute()
{
// Populate Stub List
GetAllPlacesAction.populateStubList(this.places);
// Forward
return SUCCESS;
}
public String sortByAdress()
{
// Refresh comparator class name
this.comparatorClassName = "ois.AddressComparator";
// Populate Stub List
GetAllPlacesAction.populateStubList(this.places);
// Forward
return SUCCESS;
}
public String sortByAlphabet()
{
// Refresh comparator class name
this.comparatorClassName = "ois.AlphabetComparator";
// Populate Stub List
GetAllPlacesAction.populateStubList(this.places);
// Forward
return SUCCESS;
}
private static void populateStubList(List<PlaceBean> p_places)
{
// Populate Stub List
p_places.add(new PlaceBean("Gabriel", "USA"));
p_places.add(new PlaceBean("Kim", "South Corea"));
p_places.add(new PlaceBean("Khofi", "Ghana"));
p_places.add(new PlaceBean("Abel", "Germany"));
}
This example may be improved by more experienced users. But for the moment it's enough to display a list, and two buttons to change the way its items are sorted. Good luck ;-) #+
<s:sort comparator="?how to pass enum class here?" source="places">
<s:iterator status="status">
...
</s:iterator>
My enum class is -->
package com.vijay.util;
public enum ServiceComparator {
displayNameAndEffectiveAt{
#Override
public int compare(ServiceContract sc0, ServiceContract sc1) {
//code
}
};
}

How to get the checked Checkbox values from GSP to java script

Hi I am new to grails and GSP
I have a code like
<g:each var="i" in="${typeList}">
<g:if test="${i != null}">
<tr>
<td><input type="checkbox" name="categoryType" id="categoryTypeCB" class="categoryTypeCB" value="${i}"> ${i}</td>
</tr>
</g:if>
</g:each>
How to get the values of checked check boxes in java script
Try to use jQuery. Since Grails 2.0 it's provided by default, you just have to add in your gsp template at the end of head tag with following line:
<r:require module="jquery" />
Or if you do not use resources plugin, include jQuery with following line:
<g:javascript library='jquery' />
And then in a javascript block go with:
<g:javascript>
var checkedCheckboxes = $('.categoryTypeCB:checked');
$.each(checkedCheckboxes, function(index, checkbox) {
var theValue = checkbox.value;
});
</g:javascript>
The each funciton is a loop so you need to handle somehow 'theValue' each iteration. The checkbox argument contains the input element itself if you need it.
BTW. You shouldn't assign the same id for many inputs. It's incorrect. Id has to be unique for each HTML element among document tree.

Struts2 url rewriting to populate data to next page via Actionsupport Page

Little confused in Struts2
1)Page A displays Iteration data - say 20 unique Records
2)Need to call a new Page B from Page A with Selection of any 1 data
3)Data passed from Page A has to be preprocessed from DB with additional specific
Data and the same need to be displayed on Page B
ex --
1) Page A
<s:iterator value="SRCHARRDTA" var="itms">
<tr>
<td nowrap width="20%"><s:property value="%{#itms.FileName}" /></td>
<td nowrap width="20%"><s:property value="%{#itms.FileCategory}" /></td>
<s:hidden name='FILECONTENT' value='%{#itms.FileName}' />
</iterator>
<td nowrap width="10%">
<a href="<s:url namespace='/SrchData' action='Src5'/>" >
<s:label cssClass='labelsdef' key='label.srchtype2' /></a>
</td>
</tr>
2) Retrieve the specific value via 'FILECONTENT' to Struts2 based
"abcd extends ActionSupport" class
Fetch the Data as per 'FILECONTENT' from DB
Set the Bean values in same calss
3) Page B
Iterate the beans and display same on Page B
How can 1,2,3 this be done ???
Need a small sample Code ..... please
Skip this process of DB retrival data [ i already know this part ]
with regards
karthik
It seems quite straight forward.
All we need to define an action with one property which will capture the value of file content being sent from page A along with an iterator which contain the values being fetched from the DB.
public class FileContentAction extends ActionSupport{
private String FILECONTENT;
// getters and setters
private List<YourBean> beanList;
// getters and setters for this
public String execute() throws Exception{
Fetch the Data as per 'FILECONTENT' from DB
Set the Bean values in same calss
return SUCCESS;
}
}
now you need to define the result in your config file.
<action name="filecontent" class="com.demo.FileContentAction">
<result>/pageb.jsp</result>
</action>
and in b.jsp
<s:iterator value="beanList" var="list">
// since your bean will be top of value stack
// do what ever you want to display
</s:iterator>

Resources