Updating only the partial view contained in the mvc 3 page?

I have an MVC 3 page that returns a list of user responses with a partial view called "memo" (which displays / adds notes) for each answer. When I add a reminder of the answer, it should update db and the list of notes for this answer. This should be a partial page refresh via ajax, which only affects the partial memo view.

View Response.chtml containing "memo":

@using (Html.BeginForm("Response", "User", FormMethod.Post, new { id = "UserResponse" })) { .... code removed .... @foreach (var response in Model) { <div class="qna"><input type="text" id=@response.responseId value="@response.ResponseText" /> <div>@Html.Partial("_memo", response.responseId)</div> } ..... 

Partial page "_memo.chtml":

 <div>add memo</div> <ul id="memos"> @foreach (var memo in Model) { <li>@memo.Text</li> } </ul> <form method="post" id="memoForm" action="@Url.Action("AddMemo")"> @Html.TextArea("Memo", new { rows = 5, cols = 50 }) <br /> <input type="submit" value="Add" /> </form> 

Controller to view User / Response:

 [HttpGet] public ActionResult Response(id) { ..... return View(responses); 

I just started with the code above, you need help filling in the blanks.

  • If I pass the partial view response identifier, how do I pull the note list for this response? Will this include ajax? (instead of .. Partial("_memo", response.memos) )

  • How to update a partial view through an ajax call. What is an ajax call (sample code) on the client side and what will the controller look like? When the ajax call is successful, how do I update the notes list div="memos" to reflect the new note?

  • Will the form action from the response conflict with the action of the Memo partial view form?

+4
source share
2 answers

Answers on questions:

  • You do not have to pass the responseId partially, you must pass the memo collection from your response object and make the partial view strictly entered into this collection.
  • See the full code example below.
  • You do not need a partial form, as you make a simple ajax call to add a new note. See the full code example below.

This is a modified example project that I am currently working on:

Below are a few codes, therefore:

This is my model. There are several sections in the career planning form, one of which is the section for selecting and updating competencies. The SelectCompetencies model has a set of competencies within it. The user will be able to add competencies. When they do, it will be added to the database and will update the list of competencies in partial.

 public class CareerPlanningFormViewModel { // code removed ... public SelectCompetenciesModel SelectCompetencies { get; set; } // code removed ... } public class SelectCompetenciesModel { public int CareerPlanningFormID { get; set; } public IList<CompetencyModel> Competencies { get; set; } public byte MaximumCompetenciesAllowed { get; set; } } public class CompetencyModel { public int CompetencyID { get; set; } public int? CompetencyOptionID { get; set; } public string ActionPlan { get; set; } public IDictionary<int, string> CompetencyOptions { get; set; } } 

The main view of the career planning form: /Views/CPF/CareerPlanningForm.cshtml

 @model MyNamespace.Models.CareerPlanningForm.CareerPlanningFormViewModel <link rel="stylesheet" href="@Url.Content("~/Content/CreateCPF.css")" /> @using (Html.BeginForm()) { // other sections loaded here... // code removed for brevity... @Html.Partial("SelectCompetencies", Model.SelectCompetencies) // other sections loaded here... // code removed for brevity... } 

Partially SelectCompetencies: /Views/CPF/SelectCompetencies.cshtml The user fills in the new text of the action plan and click the Add Competency button. This message will be sent via ajax to CPFController / NewCompetencyTemplate

 @model MyNamespace.Models.CareerPlanningForm.SelectCompetenciesModel @Html.HiddenFor(m => m.CareerPlanningFormID) <h3>Select Competencies</h3> <p class="guidance"> Select up to @Model.MaximumCompetenciesAllowed competencies to focus on improving. </p> <table id="CompetenciesTable"> <thead> <tr> <th>Competency</th> <th>Action Plan:</th> </tr> </thead> <tbody> @for (int i = 0; i < Model.Competencies.Count(); i++) { @Html.EditorFor(m => m.Competencies[i]) } </tbody> <tfoot id="CompetenciesTableFooter" class="@(Model.Competencies.Count() < Model.MaximumCompetenciesAllowed ? "" : "hidden")"> <tr> <td colspan="2"> @Html.TextArea("NewActionPlanText") @Html.Button(ButtonType.Button, "Add Another Competency", "add", new { id = "AddCompetencyButton" }) </td> </tr> </tfoot> </table> @section script { <script> jQuery(document).ready(function ($) { var competenciesTableBody = $('#CompetenciesTable tbody'), competenciesTableFooter = $('#CompetenciesTableFooter'), addCompetencyButton = $('#AddCompetencyButton'), newCompetencyTemplateUrl = '@Url.Content("~/CPF/NewCompetencyTemplate")', count = competenciesTableBody.find('tr').length, newActionPlanText = $('#NewActionPlanText'), careerPlanningFormID = $('#CareerPlanningFormID'); addCompetencyButton.click(function () { $.ajax({ url: newCompetencyTemplateUrl(), type: 'POST', data: { careerPlanningFormID: careerPlanningFormID, actionPlan: newActionPlanText, itemCount: count }, dataType: 'html', success: function (data) { var elements = $(data); // other code removed here... competenciesTableBody.append(elements); // other code removed here... } }); }); }); </script> } 

Views / CPF / EditorTemplates / CompetencyModel.cshtml

 @model MyNamespace.Models.CareerPlanningForm.CompetencyModel <tr class="competency"> <td> @Html.DropDownListFor(m => m.CompetencyOptionID, new SelectList(Model.CompetencyOptions, "Key", "Value"), "Select competency...") </td> <td> @Html.TextAreaFor(m => m.ActionPlan, new { @class = "competencyActionPlan" }) @Html.HiddenFor(m => m.CompetencyID) </td> </tr> 

A controller containing an action to add a new competency: /Controllers/CPFController.cs

This will call the CareerPlanningFormService to add a new competency and return a partial view for the NewCompetencyTemplate that displays the new competency

 public class CPFController : Controller { private readonly ICareerPlanningFormService careerPlanningFormService; public CPFController(ICareerPlanningFormService careerPlanningFormService) { this.careerPlanningFormService = careerPlanningFormService; } [HttpPost] public PartialViewResult NewCompetencyTemplate(int careerPlanningFormID, int itemCount, string newActionPlanText) { var count = itemCount + 1; // Even though we're only rendering a single item template, we use a list // to trick MVC into generating fields with correctly indexed name attributes // ie Competencies[1].ActionPlan var model = new SelectCompetenciesModel { Competencies = Enumerable.Repeat<CompetencyModel>(null, count).ToList() }; model.Competencies[count - 1] = this.careerPlanningFormService.BuildNewCompetencyModel(careerPlanningFormID, newActionPlanText); return this.PartialView(model); } } 

My class of service: CareerPlanningFormService.cs

This handles the business logic and forces calls to the repository to add an item to the database and returns a new CompetencyModel

 public class CareerPlanningFormService : ICareerPlanningFormService { private readonly IMyRenamedRepository repository; private readonly IPrincipal currentUser; public CareerPlanningFormService( IMyRenamedRepository repository, IPrincipal currentUser) { this.repository = repository; this.currentUser = currentUser; } public CompetencyModel BuildNewCompetencyModel(int careerPlanningFormID, string newActionPlanText) { var competency = new Competency { CareerPlanningFormID = careerPlanningFormID, CompetencyOptionID = null, ActionPlan = newActionPlanText }; this.repository.Add(competency); this.repository.Commit(); return new CompetencyModel { CompetencyID = competency.CompetencyID, CompetencyOptionID = competency.CompetencyOptionID, ActionPlan = competency.ActionPlan, CompetencyOptions = this.GetCompetencyOptionsForCareerPlanningFormID(careerPlanningFormID) }; } } 

Now partial for NewCompetencyTemplate: Views / CPF / NewCompetencyTemplate.cshtml

It's very simple, it just displays the same editor template as above for the last competency in the collection (which we just added)

 @model MyNamespace.Models.CareerPlanningForm.SelectCompetenciesViewModel @Html.EditorFor(m => m.Competencies[Model.Competencies.Count() - 1]) 

When the ajax call succeeds, it will get this partial reverse side from the controller action method it invoked. Then it takes a partial and adds it to the body of the competency table

 // snippet from ajax call above competenciesTableBody.append(elements); 

Hope this helps. Let me know if you have further questions.

+2
source

While you're right that you can do this by simply returning a partial view containing the updated content, you can also consider using the jQuery download method.

Take a look here , in particular at the "fragments of the download page" section. Basically, you can simply restore the original page, and jQuery will β€œextract” the content you want as long as it can be set to a selector (for example, div id).

Note. This solution is not suitable in all cases, since the server response will have excessive markup, because you will discard the rest of the page content and just use the updated part.

+1
source

All Articles