I have a select field to choose the department. I want to implement a view that displays the list of employees working in that department. I want to display both the select field and list of employees in the same page(view). How is it possible to send the selected field parameter to the same controller and update the list of employees object and display the list in the same page.
There are three main parts to a partial page update. I will give you a general overview of how each part is composed with some examples. This should get you started on the right path. I'm having to make lots of assumptions since your question is light on details. However you should be able to take this information and write your won implementation.
Part 1 (Making the request)
This involves monitoring the select list for a change and sending the value of the selected option to the controller. JQuery is well suited for this. I am going to pretend that the select list has an id of "departmentId" and we want to put the contents of the employee list into an element with the id of "displayList".
<script type='text/javascript'>
<!--
(function() {
$("#departmentId").on("change", function() {
$.get("${g.createLink(controller: 'employeee', action: 'listForDepartment')}/"+$(this).val(), function(data) {
$("#displayList").html(data);
});
});
})();
// -->
</script>
Part 2 (Fulfilling the request)
The second part is our controller code for getting the list of employees. This is just an example of what it might look like. Notice that we are going to render a template instead of a view. This is very important because we don't want Grails (Sitemesh) to apply any layout to the results.
class EmployeeController {
...
def listByDepartment() {
def model = [:]
model['department'] = Department.get(params.id)
model['employees'] = Employee.findAllByDepartment(model['department'])
render template: 'employeeListForDepartment', model: model
}
...
}
Part 3 (Displaying the results in a template)
Finally, our template grails-app/views/employee/_employeeListForDepartment.gsp is going to display our employees for the department. Since we used the employee controller the template is inside the employee views and all templates begin with an underscore.
<h1>Employees for ${department.name}</h1>
<ul>
<g:each in="${employees}" var="employee">
<li>${employee.name}</li>
</g:each>
</ul>
Of course, the details of your implementation my be very different but the overall concept should be the same. This just touches on the main part of this and leaves a lot of details out, such as spinners, canceling requests, and such.
Related
I have a 'home' controller which deals with the basic Home, About, Courses, Contact pages. There are multiple courses available, each with their own page and I would like to know the best method for referencing these pages. I could just create them as additional pages and add an actionresult to the home controller for each page. So the url for a course would be home/course1. Presumably there is a much better method than this though.
Ideally I'd like to have the individual course pages in a separate folder within the view folder and their url to be /home/courses/course1. Can anyone explain the best method using MVC for organising these pages?
So it goes like this : There will be a single page for all the courses and all the course pages will be partial views now there will be a div on the main page and whenever user clicks one of the course name.. it will fire an ajax request and it returns the required partial and populate the div with the returned content. You can give a common class to all the links of Courses, just like this :
.<a class="couseTrigger" data-source="#Url.Action("Name of Partialview action,"
name of controller")">
------ Script -----
$('.couseTrigger').click(function(){
var _this = $(this);
var url = _this.data('source');
--then make the ajax request to this url pvariable and retrun the partial view.
});
If you have multiple courser avoid creating multiple webpages for those courses. Rather have the content of each course stored in a database and retrieve specific course content by some parameter and bind it to the webpage. Creating webpage for each course is not feasible. Suppose you have 100 courses are u gonna create 100 webpages ?
I am tasked to change our Silverlight(SL) application to MCV since the development lifecycle of SL has already been stopped. I am new to MVC but I can't find a good tutorial how to do a simple CRUD with MVC. Basically, the requirements are
1.) in the UI, there should be two pane, left and right.
2.) In left pane, a grid/data grid view of list of "Student" entity and on the
3.) right side is a data form which displays the Student's details.
4.) The details in right pane, the data form, will change as you select an item in left pane, the data grid.
5.) The data form should be able to do the CRUD functionality.
I am very desperate to find a tutorial but I can't find one that fits my needs. I will be very thankful to those who can help me with this by giving some links or video tutorial. Hope to read comments that could help.
Instead of writing some error free code, I am going to give some directions how to do this with some pseudo code. This will help you to get started.
1.) in the UI, there should be two pane, left and right.
How about adding 2 divs to your page. Try playing with the CSS (Width 50% ? float : Left etc..). This page will be the razor view of Item 2 described below.
2.) In left pane, a grid/data grid view of list of "Student" entity
You will have to create an action method called List (or whatever you like). Inside that you need to query your db and get the students, convert that to a list of view models and send it to the view. In the view, you loop through the items and display a grid, i mean an HTML table.
public ActionResult List()
{
var list= new List<StudentViewModel>();
//Hard coded for demo. you may replace with values from your db
list.Add(new StudentViewModel { Id=1, Name="Shyju" });
return View(list);
}
The view model is a simple POCO
public class StudentViewModel
{
public int Id {set;get;}
public string Name {set;get;}
}
So your List.cshtml view will be strongly typed to a list of StudentViewModel
#model List<StudentViewModel>
<table>
#foreach(var item in Model)
{
<tr>
<td>#item.Name</td>
</tr>
}
</table>
3.) right side is a data form which displays the Student's details.
Add HTML markup for creating a form ,Input fields and a save button.
will change as you select an item in left pane, the data grid.
Add some jQuery code to listen to the click event on the table row, read the StudentId (you can set this as the data attribute value of the tr) and use that Id and make an ajax call to get the data about that student, load that in the input fields.
Update the table markup to have the data attribute
<tr class="myTr" data-studid="#item.Id"><td>#item.Name</td></tr>
The javascript to listen to the click event on the tr
$(function(){
$("tr.myTr").click(function(e){
e.preventDefault();
var studId=$(this).data("stupid");
var url ="#Url.Action("Details","Student")";
//make an ajax call to get the student details
$.getJSON(url+"?id="+studId,function(res){
$("#NameFieldId").val(res.Name);
});
});
});
You need to have a Details action method to give a student detail in json format
public ActionResult Details(int id)
{
var student = new StudentViewModel();
student.Name="Read from DB and set this";
return Json(student,JsonReqestBehaviour.AllowGET);
}
5.) The data form should be able to do the CRUD functionality.
using jQuery ajax, post the form to an http post action method and save it there. Check this and this and this for reference.
I'm making the transition from webforms to MVC (I know, 3 years late) and I "get it" for the most part, but there's a few things I'd like advice and clarification on:
First off, what happens if you want to dynamically add inputs to a view? for example, in an old webform for generating invoices I had a button with a server-side click event handler that added an extra 5 invoice item rows. The stateful nature of webforms meant the server handled the POST event "safely" without altering the rest of the page.
In MVC I can't think how I'd do this without using client-side scripting (not a showstopper, but I would like to support clients that don't have scripting enabled).
The second problem relates to the invoices example. If my Model has a List, how should I be generating inputs for it?
I know data binding is a possible solution, but I dint like surrendering control.
Finally, back to the "stateful pages" concept - say I've got a Dashboard page that has a calendar on it (I wrote my own calendar Control class, the control itself is stateless, but can use the webform viewstate to store paging information) - how could a user page through the calendar months? Obviously POST is inappropriate, so it would have to be with GET with a querystring parameter - how can I do this in MVC? (don't say AJAX).
Thanks!
In MVC you design your actions to accommodate your needs. For example, if you wanted to be able to add 5 rows to an invoice NOT using client-side scripting, you'd probably have your GET action for the invoice generation take a nullable int parameter for the number of rows. Store the current number of rows in the view model for the page and generate a link on the page to your GET action that has the parameter value set to 5 more than the current value. The user clicks the link and the GET view generates the page with the requested number of rows.
Controller
[HttpGet]
public ActionResult Invoice( int? rows )
{
rows = rows ?? 5; // probably you'd pull the default from a configuration
...
viewModel.CurrentRows = rows;
return View( viewModel );
}
View
#Html.ActionLink( "Add 5 Lines", "invoice", new { rows = Model.CurrentRows + 5 }, new { #class = "add-rows" } )
You would probably also add some script to the page that intercepts the click handler and does the same thing via the script that your action would do so that in the general case the user doesn't have to do a round trip to the server.
<script type="text/javascript">
$(function() {
$('.add-rows').click( function() {
...add additional inputs to the invoice...
return false; // abort the request
});
});
</script>
Likewise for your calendar. The general idea is you put enough information in your view model to generate all the actions that you want to perform from your view. Construct the links or forms (yes you can have multiple forms!) in your view to do the action. Use parameters to communicate to the controller/action what needs to be done. In the rare case where you need to retain state between actions, say when performing a wizard that takes multiple actions, you can store the information in the session or use TempData (which uses the session).
For things like a calendar you'd need the current date and the current view type (month/day/year). From that you can construct an action that takes you to the next month/day/year. For a paged list you need the current page, the current sort column and direction, the number of items per page, and the number of pages. Using this information you can construct your paging links that call back to actions expecting those parameters which simply do the right thing for the parameters with which they are called.
Lastly, don't fear AJAX, embrace it. It's not always appropriate (you can't upload files with it, for example), but your users will appreciate an AJAX-enabled interface.
In MVC you can store application state in various ways. In your controller you have direct access to the Session object and you can also store state to the database.
your view can contain basic control flow logic, so, if your model has a list you can iterate over it in the view and, for example, render an input control for each item in the list. you could also set a variable in a model to be the maximum number of rows on the viewpage and then render a row in a table for the number specified by the model.
paging is basically the same thing. you can create a partial view (user control in the webform world) that shows page numbers as links, where each link calls an action that fetches the data for that page of results.
i'm not sure what your beef is with ajax or javascript
I am new to ASP.NET MVC, particularly ajax operations. I have a form with a jquery dialog for adding items to a drop-down list. This posts to the controller action.
If nothing (ie void method) is returned from the Controller Action the page returns having updated the database, but obviously there no chnage to the form. What would be the best practice in updating the drop down list with the added id/value and selecting the item.
I think my options are:
1) Construct and return the html manually that makes up the new <select> tag
[this would be easy enough and work, but seems like I am missing something]
2) Use some kind of "helper" to construct the new html
[This seems to make sense]
3) Only return the id/value and add this to the list and select the item
[This seems like an overkill considering the item needs to be placed in the correct order etc]
4) Use some kind of Partial View
[Does this mean creating additional forms within ascx controls? not sure how this would effect submitting the main form its on? Also unless this is reusable by passing in parameters(not sure how thats done) maybe 2 is the option?]
UPDATE:
Having looked around a bit, it seems that generating html withing the controller is not a good idea. I have seen other posts that render partialviews to strings which I guess is what I need and separates concerns (since the html bits are in the ascx). Any comments on whether that is good practice.
look at the ContentResult you can specify the mime type of what you return (text/html)
You could alternatively make a control that take a IEnumerable of whatever you put in the selectlist, and build it using the view engine. That way you keep the formatting of the html (in this case a list of options) into a view, and not in your code.
<%# Control Language="C#"Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Article>>"%>
<%foreach (var article in Model){%>
<option><%:article.Title %></option>
<%} %>
I think I would go for that second one
From what I understood, the jQuery dialog contains a form that, when submitted, will post to an action which updates the database with some information. You want to get the newly added database information and update the same form that was used to trigger the database update.
If that is the case, then I think the best clean and logical option is to return JSON serialization of the items to be put in the drop down right after you update the database. Then, using jQuery, you would clear the drop down and append option tags into it.
You can also write a new, seperate action that returns the JSON serialization of the database objects you need. You would have jQuery call another post to this action as a callback to your first ajax post (the one used to update the database).
Here is a quick snippet
public ActionResult UpdateDatabase(string something)
{
/// update the database
IEnumerable<Items> items = getItemsFromDatabase(); // or w/e
var vals = items.Select(x=> new { value = x.ID, text = x.Name }); // something similar
return Json(vals);
}
Personally, I would write a separate function that returns JSON. This ensure separation of concerns, and gives me a function I can use in many different places.
Returning a JsonResult with all the items is the most versatile and least-bandwidth intensive solution as long as you are happy to iterate through the list in jQuery and update your drop-down list.
Using a partial view is nice for HTML that you can .load(...) directly into your select, but less versatile.
I would go with the JsonResult.
In your Controller:
public JsonResult UpdateItem(string sItem)
{
// 1. Insert new item into database if not exist...
// {update code here}
// 2. retrieve items from database:
IEnumerable<Item> Items = GetItems();
// 3. return enumerable list in JSON format:
return new JsonResult{ Data = new {Items = Items, Result = "OK" }};
}
On client-side:
Iterate through Items array and add the items to your list.
I've got a nice MVC app running now, and I'm adding some AJax functionality. I have a table which displays 10 items, only certain users can see certain items. When the user adds a new post I've set-up the ajax to save the new entry.
However I then need to update the table, I cant find out from JQuery what status the user is (And hence what they can see) so I cant just insert a new row (As some users cant see that row). If this was web-forms I would likly have a page that dumps the table and then i would use JQuery to load the contents of that trimed down 'page' into the relevent slot on the current page.
Whats the best way to achieve this with MVC?
Thanks
As #Robert Koritnik suggests, the best way to handle this is using a PartialView. I would suggest having two separate controller actions -- one that handles the original request and another that handles the AJAX new entry. Both actions would call the same logic to get the data for the table. The former would put the data into the view model along with other page data. The latter would package the data into a model for the partial view.
Model classes
public class PageViewModel
{
....
public IEnumerable<TableViewModel> TableData { get; set; }
}
public class TableViewModel
{
...
}
Controller Code
[AcceptVerbs( HttpVerbs.Get )]
public ActionResult Index()
{
var model = new PageViewModel();
model.TableData = GetTableForUser( this.User );
return View( model );
}
[AcceptVerbs( HttpVerbs.Post )]
public ActionResult AddEntry( ... )
{
... add the new entry ...
var model = GetTableForUser( this.User );
return PartialView( "TableView", model );
}
private TableViewModel GetTableForUser( IIdentity user )
{
...
}
View Code
Main View
<% Html.RenderPartial( "TableView", model.TableData ); %>
<script type="text/javascript">
$('#entryForm').submit( function() {
$.post( '<%= Url.Action( "addentry", "controller" ) %>',
$('#entryForm').serialize(),
function(data) {
$('#table').replaceWith( data );
},
'html' );
return false;
});
</script>
TableView
<table id="table">
<% foreach (var row in Model) { %>
<tr>
...
</tr>
<% } %>
</table>
Use PartialView functionality that will return just the <table> you need. In your main page it will be included but in your Ajax call it will only emit HTML back to the client that you can use to replace existing <table> element.
If I understand you correctly, you're saying that user A is viewing a list of entries and user B (In some other part of the world. maybe) posts a new entry. You want the list on user A's screen to update, but only if the new entry is one that user A is allowed to see?
If this is the case, you can have a timer running on the page and, when the timer triggers, it causes an AJAX call to the server, asking if there are any new entries for the user. The identity of the user and - therefore - which items they can see, should be determined from the session (Exactly how this works depends on your particular architecture, but I'd guess that you're already doing this, to display the list of items for user A to start with)
There are all sorts of fine details to consider here...
How often should the timer trigger, in order to get updates in a timely manner, but without causing too much traffic to the server
Should you simply update the entire list (This makes the code simple) or should you only download new items (This makes the logic more complicated, but also keeps the traffic smaller)
How do you ensure that you correctly identify the user, and correctly filter the entries to show only the relevant ones.
It's a relatively simple scenario - and ones that's no too uncommon - but it needs to be approached in a sensible manner to prevent complication setting in.
It's not hard to add a cookie which will store the current status of the user, or you can simply add another Ajax call to find out whether the user is authorized or no. you simply create some items in your controller to handle all the situations: whether user is authorized or no, what you show/hide from them.
what exactly do you need thou?