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); </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;
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.