9

Every example that I can find of an MVC4 app has the edit working on one row of data at a time. It displays all the rows of data with each row having an edit which takes you to another page and allows you to edit that one row.

What I would like to do is display all the data elements in rows and instead of having the user have to click EDIT on each row, all the rows' data points would already be in text boxes which the user can directly update. And there is just one SAVE on the page that would just save all the updates/edits at once.

How can I setup my MVC app to support that?

tereško
  • 58,060
  • 25
  • 98
  • 150
dan27
  • 1,425
  • 3
  • 14
  • 13
  • Are you looking for a postback or ajax model for sending updates? – Heather Nov 20 '12 at 23:06
  • I guess I would be looking for the simplest right now...as I am just learning MVC4. Assuming that would be postback. But I can work with either model. thanks – dan27 Nov 20 '12 at 23:11

2 Answers2

12

You can use an EditorTemplates for this. The below example shows the normal form posting example. You can ajaxify it if you need by using the serialize method and sending form values.

Assuming You need to Edit the List of Student Names for a course. So Let's create some viewmodels for that

public class Course
{
  public int ID { set;get;}
  public string CourseName { set;get;}
  public List<Student> Students { set;get;}

  public Course()
  {
    Students=new List<Student>();
  }
}
public class Student
{
  public int ID { set;get;}
  public string FirstName { set;get;}
}

Now in your GET action method, you create an object of our view model, initialize the Students collection and send it to our strongly typed view.

public ActionResult StudentList()
{
   Course courseVM=new Course();
   courseVM.CourseName="Some course from your DB here";

   //Hard coded for demo. You may replace this with DB data.
   courseVM.Students.Add(new Student { ID=1, FirstName="Jon" });
   courseVM.Students.Add(new Student { ID=2, FirstName="Scott" });
   return View(courseVM);
}

Now Create a folder called EditorTemplates under Views/YourControllerName. Then create a new view under that called Student.cshtml with below content

@model Student
@{
    Layout = null;
}
<tr> 
 <td>
  @Html.HiddenFor(x => x.ID)
  @Html.TextBoxFor(x => x.FirstName ) </td>
</tr>

Now in our main view (StudentList.cshtml), Use EditorTemplate HTML helper method to bring this view.

@model Course
<h2>@Model.CourseName</h2>
@using(Html.BeginForm())
{
  <table>
     @Html.EditorFor(x=>x.Students)
  </table>
  <input type="submit" id="btnSave" />
}

This will bring all the UI with each of your student name in a text box contained in a table row. Now when the form is posted, MVC model binding will have all text box value in the Students property of our viewmodel.

[HttpPost]
public ActionResult StudentList(Course model)
{
   //check for model.Students collection for each student name.
   //Save and redirect. (PRG pattern)
}

Ajaxified solution

If you want to Ajaxify this, you can listen for the submit button click, get the form and serialize it and send to the same post action method. Instead of redirecting after saving, you can return some JSON which indicates the status of the operation.

$(function(){
  $("#btnSave").click(function(e){
    e.preventDefault();  //prevent default form submit behaviour
    $.post("@Url.Action("StudentList",YourcontrollerName")",
                    $(this).closest("form").serialize(),function(response){
   //do something with the response from the action method
    });
  });
});
Aligma
  • 562
  • 5
  • 29
Shyju
  • 214,206
  • 104
  • 411
  • 497
  • Okay, this is working great. Question: What if your Student class above has a GenderId element and that is a foreign key to a Gender class with int GenderId, string GenderName. I want to display/edit the GenderName in the form so it is more user friendly, but update the genderid. I can get the gendername to display, but whenever I update it, it came back null. Do I need to nest EditorTemplates? – dan27 Nov 21 '12 at 19:49
  • @dan27: Remember these are ViewModel classes which are specific for views. It is not domain model classes. So you do not need to create another class to hold geneder. Keep it simple and have gender name & id in the same student class. – Shyju Nov 21 '12 at 21:47
1

You just need to specify the right model, list of example, and send the ajax with have information on each row (element of the array), read it on the server side and update each element accordingly. For this goal you use Post request. Just pass the list of elements as a parameters into the controller and pass it using the ajax.

For example you controller could be defined as:

public ActionResult Update(List<MyEntity> list)
{
...
}
public class MyEntity
{
public string Name {get; set;}
public int Count {get; set;}
}

and JavaScript could be as:

var myList = new Array();
// fill the list up or do something with it.

$.ajax(
{
   url: "/Update/",
   type: "POST",
   data: {list: myList}
}
);

And of course your "Save" button has click event handler that will call that functionality with the ajax call.

For your convenience you can consider using KnockoutJS or other MVVM frameworks to bind the data with the DOM on the client side.

Kath
  • 1,834
  • 15
  • 17