Populate drop down menu Grails - grails

I am currently trying to populate a drop down menu based upon the selection in the previous drop down menu I have. For example if you click on Spring 2013 in the first drop down menu the second menu will show all the respective weeks assigned to that semester so that one can be chosen and modified. How do I propagate the second menu with respects to the choosing from the first menu?
This is my controller:
class TermController {
static scaffold = Term
def dataSource
def list = {
def db = new Sql(dataSource)
def result = db.rows("SELECT id, semester FROM term")
[ result: result ]
}
}
Here is my list.gsp to show the view of the controller:
<div class="fieldcontain">
<g:select name="termSelection" from="${Term.list()}" values="${params.id}" optionKey="id" optionValue="semester" noSelection="['':'----Term----']"/>
</div>
<table>
<tr>
<g:select name="it.week" from="${Week.list()}"/>
</tr>
</table>

It looks to me like you want to make an ajax call triggered by the selection change of another list?
Listen to changes in your termSelection list
Upon changes, make an ajax call to retrieve the list of weeks
Feed the retrieved ajax List to your it.week list

Related

CRUD, create and update functionality on same view : ASP.net MVC2 + EF

I am a newbie and is making web application in Visual Studio 2010 using MVC2 + Entity framework.
I have a situation in which I want to put both operations i.e create user / update user at same view, I have also tried attaching relevant picture where I have made two portions one for create user and second for manage users.
My 'create user' fields are at top of website and when user click 'create button' page got refreshed and all enlisted users gets displayed on same view under second portion 'manage users' showing link to edit/delete them.
I want that when I click on edit link, that particular entity fields get populated on same view in first portion 'create user' where I can modify them and press 'update button'
VIEW
<%# Page Language="C#" MasterPageFile="~/Views/Shared/Admin.Master" Inherits="System.Web.Mvc.ViewPage" %>
<%# Import Namespace="MyNamespace" %>
<h4>Create New User</h4>
<form method="post" action="/Lignum/CUser">
<label for="inputEmail3">Full Name</label>
<input type="text" name="Fullname" id="txtFullname" >
<label for="inputEmail3">Email</label>
<input type="email" name="Email" id="Email1">
<button id="btnCUser" class="btn btn-primary">Create</button>
</form>
<h4>Manage Users</h4>
<table>
<tr>
<td>Sr#</td><td>Name</td><td>Email</td><td></td>
</tr>
<% int i=0;
foreach (MyWebsite.Models.User objUser in ViewData.Model as IEnumerable<MyWebsite.Models.User>)
{%>
<tr>
<td><%= ++i%></td>
<td><%= objUser.Fullname%></td>
<td><%= objUser.Email%></td>
<td>
Edit
</td>
</tr>
<%}%>
</table>
CONTROLLER
public ActionResult Index()
{
return View("UserMgt", _repositoryUser.SelectAll());
}
public ActionResult Edit(object Id)
{
if (Id != null && Id.ToString().Trim().Length > 0)
{
int param = int.Parse(Id.ToString());
return View("UserMgt", _repositoryUser.SelectByID(Id));
}
return View("404");
}
You will need to make use of JQuery & Ajax to achieve this. Your page is getting refreshed most likely because your are submitting a form. Instead of form submit, you need to attach a function to handle onclick event.
In that function you will know which item is clicked, load the data to be edited from the server sending an ajax request with item id.
When request return you can then open a JQuery popup window or update page's html to display data. User will be allowed to make changes and on Ok button click you can again send the data back to server to save.
I am looking for an example online to refer to you as my code is little complex. You can also look for an example online.
UPDATE:
i want that when i click on edit link, that particular entity fields
get populated on same view in 1st portion 'create user' where i can
modify them and press 'update button'
Ok, looked at your code. As I said earlier you will need to define an "id" for each html element, the value will be objUser.UserId (you can prefix something if you want). Now define a click event for all html elements i.e. .
For a working example refer this link.
I suggest you progress as you gain some insight and post updated code. We will suggest what's needed for next step. This way you would learn more.
You can try following:
Create a View model with whatever you need on the create page i.e. user details
strongly bind your view with this view model
Have three action methods in controller "Create","Populate" and "Update" with Update and Populate taking Id of the entity as input (you can choose better names)
Initially call Create method which will just return an empty view model with your View
Have a hidden variable in view which will store the Id of the entity (in case of create this will be zero)
on click of create just take the value of this hidden variable and do a post to Update action method.In this case if it is new entity id will be zero
On click of edit go call Populate method with id of the entity which again will return ViewModel with entity details loaded to the same create view (also set the hidden variable with id)
In your update method based on the id perform create or update operation i.e. Create for zero and Update for 1
If you post your code or other details I can give some more details using code.
EDIT: OK few more details in terms of code.
//This is the view model you need to bind to your view
public class UserViewModel
{
public int UserId { get; set; }
public string Email { get; set; }
public string FullName { get; set; }
public List<Users> UserList {get;set;} //For binding to the grid
}
Below are the action methods in controller.
public ActionResult Create()
{
var viewModel = new UserViewModel();
//Logic: Create empty view model for create
return View("UserMgt", viewModel);
}
public ActionResult Edit(int id)
{
var viewModel = new UserViewModel();
//Logic: populate the view model based on the id
return View("UserMgt", viewModel);
}
// Call this method using Jquery ajax
public bool Update(UserViewModel user)
{
if (user.Id == 0)
//Logic : Create the user
else
//Logic : Edit the user
return Json(status); //Status = true if successful else false
}
Initially call create.On click of edit call Edit method.On click of save call Update.
For using jquery ajax follow below link
http://api.jquery.com/jquery.ajax/

How to Send a Javascript Variable to a Grails Controller to Query Neo4J

I'm a newbie trying to find uses for Neo4J on Grails.
Basically, I've made 20 grocery item nodes through the Neo4J browser and I want to create a simple Grails site that will let users search a grocery item and visually show the items related to it.
My index.gsp has:
<input id="item" />
My viz.js has:
$('#item').keyup(function() {
var item = $('#item').val();
My Item Domain class has
class Item {
static mapWith = "neo4j"
String name
My ItemController class has:
def index() {
def item = Item.list() [item:item] //No idea, just trying out whatever i find :(
and a query with something like:
def query = Item.cypherStatic ("""start n=node({Item}) match (n)-[r]->(x) where r='partner' return n, x)
Questions:
How can I properly send the JS 'item' variable into the ItemController?
How can I use the 'item' variable to properly query the node names which have a 'partner' relationship with the item?
in addition to Motilals answers, you definetly need a wrapping form with an action that points your controller
like
<g:form controller="itemController" action="index" >
<input type="text" id="item" name="item" value="" />
<input type="submit" value="submit" >
</g:form>
then on clicking submit the for will call your index action and there you could parse the value with
def item = params.item
but it looks more like you want some asynchronous stuff right after keyup-function, therefore you could do sth like this :
$('#item').keyup(function() {
var item = $('#item').val();
$.ajax({
url: "${createLink(controller:'itemController', action:'index')}",
data:"&item="+item
})
.done(function( data ) {
console.log(data)
});
});
in this case, you need to pay attention what your index-action is returning, so you can do in the .done() whatever you want with the response.
also note, that when you name an action "index" it will be available at
.../myproject/item/index
or, and thats important
.../myproject/item/
so if your index method requires the data from the input, it will miss them if a user has gone straight to that url
so your index action would rather render the page with the input
and you define another action for executing your query based on input and returning data
set the item to hidden field and then you can access it directly in your controller using params
here you go:
//in index.gsp add below hidden field and set the hidden filed in your js code
<g:hiddenField name="item" value="" />
$('#item').keyup(function() {
var item = $('#item').val();
//in your controller
def index() {
def item = params.item
print item // you see the value for item
//do your stuff
}
once you have item value you could directly use HQL query or use the domain instance
hope this helps you
Regards
Motilal

How to access the Model from the View?

I have a search page that display a search result. The search result is a list of persons that matched the specific search. I'm iterating through this list displaying them in a table. As headers for this table I want the DisplayName from the model. If I don't inherit IEnumerable I wouldn't be able to iterate through the list. I'm new at this MVC thing =)
I iterate through the result like this:
<% foreach (var item in Person) { %>
<%: item.surname %>
<% } %>
But how do I print the "DisplayName" of an attribute without iterating through the whole list? I would just like to do:
<%: Html.LabelFor(m => m.surname) %>
If it's any help I inherit an IEnumerable at the top of the page:
<%# Page Inherits="System.Web.Mvc.ViewPage<IEnumerable<RegistryTest.Models.Person>>" %>
Edit
I want to display "Your surname" but I don't know how to access it from the view.
[DisplayName("Your surname")]
public object surname { get; set; }
Here's a very similar question that hasn't been answered either: Can I use LabelFor() when the page inherits from IEnumerable<T>?
If you only need to display specifics of one person; you should consider sending only one person to the view instead of a complete list of persons. In that case
Model.Surname
would work just like that. So instead of:
Inherits="System.Web.Mvc.ViewPage<IEnumerable<RegistryTest.Models.Person>>"
do
Inherits="System.Web.Mvc.ViewPage<RegistryTest.Models.Person>"
In this case a single person is loaded into your Model and Model.Property works fine. If you want an IENumerable<>, think about what that means. You are sending a list of persons, so the only thing in your "Model" is a IENumerable<> of persons. There is no way that the view can know what you want if you call Model.Property, since in the Model there are multiple Objects and the view doesn't know which Object you want to get the Property from.
Bottom line, if you want to call Model.Property (Model.surname) but also want to send an IENumerable you are having a design flaw. If you send a list you should want to do something with the complete list (iterate through and do something with the contents). If you just want to do something with one person in that list, re-design your view/controller and send that single person; then you can use Model.Property.
//EDIT BASED UPON COMMENTS
As I see it now you either want to do one of those two things (I do not know which):
Show the records of an item in your list in a table and put the DisplayName of the current object shown in the table in the header.
Show all items of the list in your table and put some sort of DisplayName in the header. This makes less sence but it could be that you mean to name your list.
Situation 1
This is working as the rest of your code? The following would work just fine.
<% foreach (var item in Model) { %>
<table>
<th>item.DisplayName</th>
<tr>
<td>item.Property1</td>
<td>item.Property2</td>
</tr>
</table>
<% } %>
Situation 2
If you want a DisplayName of the list (??) you should create a ViewModel containing the IENumerable of Persons and a public string ListName. Now you can do something like:
<table>
<th>Model.ListName</th>
<% foreach (var item in Model) { %>
<tr>
<td>item.Property1</td>
<td>item.Property2</td>
</tr>
<% } %>
</table>
this would create a table with the name of your List (given in the ViewModel) as header and as items in the table you have your persons.
Design problem?
However, I would love to see you write some more information in your question above. Give us some more information on what you want to do. Do you want to show records of each Person in the list one-by-one? In that case I would recommend you create a Partial View where you put your table. Then you would get something like:
<% foreach (var item in Model) { %>
<% Html.RenderPartial("TablePerson",item); %>
<% } %>
tableperson.ascx:
...
Inherits="System.Web.Mvc.ViewPage<IEnumerable<RegistryTest.Models.Person>>"
...
<table>
<th>Model.DisplayName</th>
<tr>
<td>Model.Property1</td>
<td>Model.Property2</td>
</tr>
</table>
So, we need more information I'm afraid :)
If it's a collection with every entry having the same surname then try model[0].surname or model.ToList().First().surname
You don't need ToList() if its a List<T> already. Then it would be just model.First()
You are specifying that the page model is IEnumerable, and you say you would like to print a property of an element. Since you have a list of elements, you need to specify which of the elements you would like to retrieve the property from.
I you want a specific index in the list you will need to convert the IEnumerable collection to IList (ToList()), depending on the criteria, you may also be able to find the required element using something like a LINQ Single() operation.
Otherwise you could select the property from all the element in the list using Model.Select(m => m.PropertyName) which will give you a list of just this property, and then concatenate this list to a single string.

asp.net mvc 3 Model with complex property and checkboxes

I have a typed view as Item (one class that i created) with a form inside to add Items to my database. This Item class has one property called Categories that is a List (Category has 2 properties ID and Name)
Im using an editorfor in my view:
<div>
#(Html.EditorFor(e => e.Categories, "Categories"))
</div>
I created an EditorTemplatefor called "Categories.cshtml" render all the available categories:
#{
Layout = null;
}
#model List<Category>
#{
foreach (Category category in ((BaseController)this.ViewContext.Controller).BaseStateManager.AvailableCategories)
{
#Html.Label("test", category.Name)
<input type="checkbox" name="Categories" value="#(category.ID)" />
}
}
The checkboxes are well rendered (one for every Available category in cache), but after clicking in some, and post the form, im receiving my instance of Item but with the property Categories empty.
What i have to do to receive my List Categories completely instantiated after submit the form?
Dont loop it. Let the framework generate the code for you (then, it will know how to build it back and bind it to your controller).
Just pass the list to the editor template and mvc will do the rest. Check my blog post on something similar.
Try using an index based loop. This ensures MVC will render the item's attributes in such a way that allows the default model binder to instantiate the model on post back. Also, use the Html helper for the checkbox as well:
var categories = ((BaseController)this.ViewContext.Controller).BaseStateManager.AvailableCategories;
for (var index = 0; index < categories.Count; index ++)
{
#Html.Label("test", categories[index].Name)
#Html.Checkbox("ID", categories[index].ID)
}

ASP.NET Collection Model Binding Nested Form Problem

I have a partial view that is bound to an object Cart. Cart has a collection of CartLines. My view is below:
<tbody>
<% foreach (var line in Model.Lines) { %>
<tr>
<td align="center"><%=Html.CatalogImage(line.Product.DefaultImage, 80) %></td>
<td align="left">
<%=Html.ActionLink(line.Product.Name, "Product", "Catalog",
new { productId = line.Product.Id }, new { title = "View " + line.Product.Name })%>
</td>
<td align="right"><%= line.Product.Price.ToString("c")%></td>
<td align="center">
<%=Html.Hidden("lines[" + i + "].key", line.Product.Id) %>
<%=Html.TextBox("lines[" + i + "].value", line.Quantity, new { #class = "quantity" })%>
</td>
<td align="right"><%= (line.LineTotal).ToString("c")%></td>
<td>
<%using (Ajax.BeginForm("RemoveFromCart", "Cart",
new {ProductId = line.Product.Id, returnUrl = ViewData["returnUrl"]},
new AjaxOptions { UpdateTargetId="cart", LoadingElementId="loading" }))
{%>
<input type="image" src="<%=AppHelper.ImageUrl("delete.gif")%>" value="Remove item" />
<%} %>
</td>
</tr>
<% i++; } %>
</tbody>
There are two things to note. The first is that I am using a form per line for removing items.
The second is that I had attempted to allow users to change the quantity of line items and then click an update button to pass all the changes to the controller action:
// POST: /Cart/Update
[HttpPost]
public ActionResult Update(Cart cart, IDictionary<int,int> lines, string returnUrl)
{
foreach (var line in lines) {
Product p = _catalogService.GetProduct(line.Key);
cart.UpdateItem(p, line.Value);
}
if (Request.IsAjaxRequest())
return PartialView("Cart", cart);
else
return RedirectToAction("Index", new { returnUrl });
}
Note that I am using a dictionary since I am only concerned about the product and quantity. I don't really like the fact that I am having to retrieve the product again before calling cart.UpdateItem but I couldn't figure out how to pass the Product from the model to my action instead of the id.
The main problem however, is rather stupidly I wrapped the entire cart in a form so that I could post back the values and then spent a good hour wondering why things were not working correctly in IE - doh! nested forms
So I am stuck on how to get round this. I want the ability to remove items individually but allow a user to change item quantities and then pass all changes at once to the controller. I can't use links for my remove action as I would need to use javascript to force a post and everything must work without javascript enabled.
[Update]
Would a better solution be to allow updates on my custom model binder? This way I could make changes inside my view and post the cart object back to the controller - although I'm not sure whether this is possible with child collections (Cart.CartItems).
I've had a look on sites like Amazon and it would appear they wrap the entire cart in a form and both global update buttons and indidivual remove item buttons post back to the same action when javascript is disabled.
Any help would be appreciated.
Thanks,
Ben
There is only one way here and thats the ugly way. Have 1 form around everything.
Then in the action you have to check which button was pressed (you get the name of the button in the request).
It gets even more ugly with differences in firefox and ie. If you have a button pressed ie or firefox (Dont remember which one) not only sends the name of the pressed button, but also the location where the button was pressed.
You have more options if your solution can rely on JS enabled browsers. But thats another story.

Resources