Help me to understand. Generated crud controller. I have a collection in the model, so I want the input fields for the elements of this collection to be added on the creation page by button.

Tried to do on the guide http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/

Now, instead of adding an input field, throws it onto a separate page with this input field.

Checklist.cs - my model

public class Checklist { public int Id { get; set; } public string Identifier { get; set; } public IEnumerable<Checks> CheckList { get; set; } public DateTime Date { get; set; } } public class Checks { public int Id { get; set; } public string Check { get; set; } } 

Create.cshtml

 @using (Html.BeginForm()) { @Html.AntiForgeryToken() <h4 align="right">New Checklist</h4> @Html.TextBoxFor(model => model.Identifier, new { @class = "form-control", @maxlength = "15", @style = "width:280px" }) @Html.ValidationMessageFor(model => model.Identifier, "", new { @class = "text-danger" }) @Html.TextBoxFor(model => model.Title, new { @class = "form-control", @maxlength = "255" }) @Html.ValidationMessageFor(model => model.Title, "", new { @class = "text-danger" }) <table id="Table"> <tr> <th>Checks</th> </tr> <tr> <td id="editorRows"> @if (Model.CheckList != null) { foreach (var item in Model.CheckList) { @Html.Partial("_create_check", item); } } </td> </tr> </table> @Html.ActionLink("Add", "BlankEditorRow", null, new { id = "addItem" }) <input type="submit" value="Create" class="btn btn-primary" /> } 

add-check.js

 $('#addItem').click(function () { $.ajax({ url: this.href, cache: false, success: function (html) { $("#editorRows").append(html); } }); return false; }); 

_create_check - partial view

 @model MyProject.Models.Checks @using (Html.BeginCollectionItem("checks")) { @Html.HiddenFor(model => model.Id) @Html.TextBoxFor(model => model.Check, new { @class = "form-control" }) } 

ChecklistsController.cs

 public ViewResult BlankEditorRow() { return View("_create_check", new Checks()); } public ActionResult Create() { Checklist checks = new Checklist(); return View(checks); } [HttpPost] [ValidateAntiForgeryToken] public ActionResult Create([Bind(Include = "Id,Identifier,Title,Date,CheckList")] Checklist checklist) { if (ModelState.IsValid) { checklist.Date = DateTime.Now; db.Checklists.Add(checklist); db.SaveChanges(); return RedirectToAction("Index"); } return View(checklist); } 

    1 answer 1

    I would advise you to make the display of PartialView on the button and hide it on another button. I will give an example:

     <div id="partialBlankEditor" style="display : none;"> @Html.Partial("BlankEditorRow", Model.LiftItems.Where(x => x.IsDeleted).ToList()) </div> 

    Since the method BlankEditorRow returns a partial view, a partial view will immediately appear after loading the page. To hide and display, you can use the display: none; property of display: none; for a div display: none; , on the main view, add a button by clicking on which we will have at partialBlankEditor change its property to display: block; for example. Here is the code:

     $('#partialBlankEditor').style.display = 'block'; 

    Hang it for example on a button instead:

     @Html.ActionLink("Add", "BlankEditorRow", null, new { id = "addItem" }) 

    let's just make a button with id:

     <button type="button" id="btn-show-editor">Show add</button> 

    Well, the processing will be as follows:

     $('#btn-show-editor').click(function () { $('#partialBlankEditor').style.display = 'block'; }); 

    Well, in the partial view, you will also need to add a button, by clicking on which we will add a value.

     @model MyProject.Models.Checks @using (Html.BeginCollectionItem("checks")) { @Html.HiddenFor(model => model.Id) @Html.TextBoxFor(model => model.Check, new { @class = "form-control" }) <button type="button" id="btn-add-new-item">Add new</button> } 

    We'll make the button click processing simple, hide the partial view, and call the Ajax method:

     $('#btn-add-new-item').click(function () { $.ajax({ url: 'CreateNew', cache: false, data: {id: '@Model.Id', check: '@Model.Check'} success: function (response) { // $("#editorRows").append(response); немного иначе нужно сделать перерисовку } }); return false; }); 

    We need to write a new method, with which we will add a new value and return a new list, and we will need to send data to Data using Ajax from @using(Html.BeginCollectionItem("checks")) . I didn’t use BeginCollectionItem , so I’ll recommend the good old @using(Ajax.BeginForm that allows you to update part of the page without reloading it entirely.

    The new method will look something like this:

     // имена должны совпасть с данными из Ajax public ActionResult CreateNew(int id, string check) { Checks newData = new Checks() { Id = id, Check = check }; // куда-то добавляем наш чек, в БД к примеру // получаем идентификатор, так как он будет нулевым, так как объект новый // newLst - это новый набор данных из IEnumerable<Checks> // можно сериализовать через JavaScriptSerializer newLst return Json(newLst); } 

    This code block raises questions and doubts:

     <td id="editorRows"> @if (Model.CheckList != null) { foreach (var item in Model.CheckList) { @Html.Partial("_create_check", item); } } </td> 

    Here it is a little unclear, maybe you wanted to display something here as a list for example? But you probably don’t need to display a partial view of adding new ones. First, in your model, CheckList will be an empty collection and no CheckList will be displayed. In general, rewrite this block of code, what is inside the foreach , so that the Ajax can then update the list, for example, through select and option , it will simply be redrawn via Ajax