I am working on grails and facing the problem that how can I get a controller's (in my case, contactGroup) data which is hasMany relations with the other (contact) controller in my layout view. Below is my domain class codes...
class Contact {
String number
String name
...
static hasMany = [groups: ContactGroup, messages: Message]
static belongsTo = [Message, ContactGroup]
}
class ContactGroup {
String groupName
String description
...
static hasMany = [contacts: Contact, messages: Message]
}
Below is my layout view code which is meant to fetch all the groups with the number of contacts enclosed in parenthesis... Just like Gmail shows the contact and group list.
<h4>Contacts</h4>
<g:link controller="contact" action="list" class="active"><h5>All (${smsserver.Contact?.list().size()})</h5></g:link>
<g:layoutBody/>
<g:each in="${smsserver.ContactGroup}" var="c">
<g:link controller="contact" action="list">${c.findAll()}<br></g:link>
</g:each>
Please help me out.
You have got m:n relations. It means 1 contact has many groups and each group has many contacts. am I right? And you would like to show all groups and all contacts from group for given contact.
ok.
Get all groups for given contact:
${contact.groups} <%-- list of groups --%>
or more suitable
<ul>
<g:each in="${contact.groups}" var="group">
<li>
${group.groupName} (${group.contacts.size()})
</li>
</g:each>
</ul>
show all groups and contacts for given contact
<ul>
<g:each in="${contact.groups}" var="group">
<li>
<b>${group.groupName}</b> (${group.contacts.size()})
<ul>
<g:each in="${group.contacts}" var="c">
<li>
${c.name}
</li>
</g:each>
</ul>
</li>
</g:each>
</ul>
Your controller:
class ContactController {
def show(long id) {
def contact = Contact.get(id)
['contact': contact]
// or
// render view:'YourPage', model:['contact': contact]
}
}
for more details http://grails.org/doc/latest/guide/theWebLayer.html#controllers
Related
The problem is that I need to "call" the PersonName field in the view of School, but the model in the view School is #model IList<Project.Presentation.Models.SchoolViewModel>, and the field PersonName is in the model #model IList<Project.Presentation.Models.PersonViewModel>. So, I guess I have to use two models in the same view, but I don't know how to do it. I don't know if I can only "call" the field I need using just one code line or if I have to do something behind.
Here is the code in the view School:
#model IList<Project.Presentation.Models.SchoolViewModel>
#{
ViewBag.Title = "Start view";
}#
{
<div class="row">
<div class="col-md-6 ">
<h2>
Details of the person #Html.DisplayFor(Project.Presentation.Models.PersonViewModel.PersonName)
</h2>
</div>
</div>
}
I'm trying with#Html.DisplayFor(Project.Presentation.Models.PersonViewModel.PersonName), but obviously it doesn't works.
your viewmodel will include all the property you will need in a view - so PersonViewModel should be a property in your viewmodel
you did not show the relationship between SchoolViewModel and PersonViewModel
but judge by the name, I am guessing it is a one to many relationship - i.e one SchoolViewModel will have many PersonViewModel representing the person in school
so base on that assumption, your SchoolViewModel may look like this:
public class SchoolViewModel
{
// other property ..
public IList<Project.Presentation.Models.PersonViewModel> PersonList {get; set;}
}
then in your view, it will look like:
#model IList<Project.Presentation.Models.SchoolViewModel>
#// first loop school
#for(int i =0; i < Model.Count; i++)
{
<div class="row">
#// then loop all person in the school
#for(int j = 0; j < Model[i].PersonList.Count; j++)
{
<div class="col-md-6 ">
<h2>
Details of the person #Html.DisplayFor(modelItem => Model[i].PersonList[j].PersonName )
</h2>
</div>
}
</div>
}
so the key is, put all your needed property to your viewmodel
Create a View Model and Include this Two Model in there
public class SchoolPersonViewModel
{
public IList<Project.Presentation.Models.PersonViewModel> PersonList {get; set;}
public IList<Project.Presentation.Models.SchoolViewModel> SchoolList {get; set;}
}
In View
<div class="row">
<div class="col-md-6 ">
<h2>
Details of the person
#Html.DisplayFor(model => model.PersonList)
</h2>
</div>
</div>
PersonList is List, So Use foreach
Same Like SchoolList
Controller class
class EntidadController {
def index(){
def entidades = Entidad.list()
[entidades:entidades]
render(view:"index")
for (x in entidades)
{
print(x.nombreEntidad)
}
}
}
Domain class
class Entidad {
String nombreEntidad
int porcentaje
static hasOne = [kiosko: Kiosko]
static belongsTo = [adminCreador: Administrador,entidadSuperior: Entidad]
static hasMany = [adminEntidad: Administrador, entidadesInferiores: Entidad]
static constraints = {
kiosko nullable:true
nombreEntidad nullable : false
adminCreador nullable : true
adminEntidad nullable : true
entidadSuperior nullable : true
entidadesInferiores nullable : true
}
}
View in gsp
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<p>test</p>
<div controller="entidadController">
<g:each in="${entidades}" var="x">
<tr>
<td>${x.id}</td>
</tr>
</g:each>
</div>
</body>
</html>
I think code is fine but i dont know why is not showing anything at the g:each tag, ive tried with a static array in gsp page and g each worked and i print at console and the array "entidades " had objects on it, its like my view cant read data from controller
Perhaps a render statement like this:
render(view:'index', model:[entidades: entidades])
If you don't need pagination and sorting in your view, you can do like this on your gsp
...
<body>
<p>test</p>
<div controller="entidadController">
<g:each in="${Entidad.list()}" var="x">
<tr>
<td>${x.id}</td>
</tr>
</g:each>
</div>
</body>
...
The problem is here:
def index(){
...
[entidades:entidades]
render(view:"index")
...
}
You are not sending entidades to the view. This can be corrected this way (render docs):
def index(){
...
render(view:"index", model:[entidades:entidades])
...
}
Also, if your view and your action share the same name, you don't need to use render method explicitly, but the map as the last line of the action (this is a grails convention). Like this:
def index(){
...
[entidades:entidades]
}
I have the following entity:
class User {
String name
String contactName
String primaryEmail
String url
String phoneNumber
String address
//..
}
I have gsp that display list of all users and I want to be able to sort users by contactName, name and phoneNumber, in the controller I have list() method that just returns list of all users:
class UserController {
...
def list() {
[users: User.all]
}
}
My gsp is like this:
<body>
<table>
<thead>
<tr>
<g:sortableColumn property="contactName" title="Bookmaker"/>
<g:sortableColumn property="name" title="Name"/>
<g:sortableColumn property="phoneNumber" title="Phone"/>
</tr>
</thead>
<tbody>
<g:each in="${users}" status="i" var="user">
<tr>
<td>${user.contactName}</td>
<td>${user.name}</td>
<td>${user.phoneNumber}</td>
</tr>
</g:each>
</tbody>
</table>
</body>
But when I click on one of the sortable columns request is sent (something like this: "list?sort=phoneNumber&order=asc") but response is always the same. Now it seems to me like code that actually sorts the list should be implemented by myself. Or am I doing something wrong? Thanks!
you again :)
def list() {
[users: User.list( params )]
}
I cant get the g:each to work. I am trying to iterate over anything but it never works = doesnt generate any html.
index.gsp
<g:each var="i" in="${userList}" controller="user">
<li>Item ${i.name}</li>
</g:each>
userController.groovy
class UserController {
...
def userList = {
User.list()
}
...
}
Then I have User.groovy filled with number of users..
What am i supposed to write in in="${.....}" to iterate for example over users declared as User.groovy ? I have tried : User, users, User.list() ...
Thanks
EDIT:
Let's say i have a
def findOne {
[users : User.findAllByNameLike("%Petr%")
}
in my UserCotroller.
How do i use g:each for it because
<g:each var="user" in="${findOne}">
won't do anything..
In your example. userList is a Closure, so it's the action name, so I'm assuming you're accessing http://localhost:8080/appname/user/userList
If you return something from a controller action to be rendered in the GSP, it has to be in a Map, the "model". Each value in the map is exposed in the GSP using the map key as its name. So the controller action corresponding to your GSP would be
def userList = {
[users: User.list()]
}
and then you can iterate with
<g:each var="user" in="${users}">
<li>Item ${user.name}</li>
</g:each>
The name doesn't matter - it just has to be the same in the model map as in the GSP.
I have two domains declared in my app.
class Posts {
String title
String content
static hasMany = [tags:Tag]
static constraints = {
}
}
class Tag {
String Name
static belongsTo = Post
static hasMany = [posts:Post]
static constraints = {
}
String toString()
{
"Tag:${Name}"
}
}
I have a controller which manages the search and display of results:
package com.trafigura.com.trafigura
class ViewerController {
def defaultAction='search'
def search={}
def show = {
def _foundPost = Post.findAllBytitle(params.title)
return [posts: _foundPost, term: params.title]
}
}
The search.gsp code is as follows:
<html>
<head><title>Simple GSP page</title></head>
<body>Place your content here.
<formset>
<legend>TagsPosts</legend>
<g:form action="show">
<label for="title">Title</label>
<g:textField name="title" />
<g:submitButton name="search" value="Search"/>
</g:form>
</formset>
</body>
</html>
and the following code for show.gsp.
<html>
<head><title>Simple GSP page</title></head>
<body><h1>Results</h1>
for items matching <em>${term}</em>.
Found <strong>${posts.size()}</strong> hits.
</p>
<ul>
<g:each var="tag" in="${posts.tags}">
<li>${tag.Name}</li>
</g:each>
</ul>
<g:link action='search'>Search Again</g:link></body>
</html>
My Question is I am unable to display the tags as follows:
Results
Found 1 hits.
* [planting, dig]
However, I want the output as:
* planting
* dig
What am I doing wrong here?
Much Appreciated.
Replace
<g:each var="tag" in="${posts.tags}">
by
<g:each var="tag" in="${posts.tags[0]}">