Adding a Add More Property to the AddMoreViewModel Model
Open the Models/AddMoreViewModel.cs file and add a Add More property:
using System.Collections.Generic;
namespace AddMoreExample.Models
{
public class AddMoreViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<AddMoreViewModel> AddMoreList { get; set; }
}
}
Open the Controller/HomeCntroller.cs file and add property:
using Microsoft.AspNetCore.Mvc;
using AddMoreExample.Models;
namespace AddMoreExample.Controllers
{
public class HomeController : Controller
{
public ActionResult MainView()
{
return View(); //this is main page.We will display "_AddMorePartialView" partial page on this main page
}
public ActionResult AddMorePartialView()
{
//this action page is support cal the partial page.
//We will call this action by view page.This Action is return partial page
AddMoreViewModel model = new AddMoreViewModel();
return PartialView("_AddMorePartialView", model);
//^this is actual partical page we have
//create on this page in Home Controller as given below image
}
public ActionResult PostAddMore(AddMoreViewModel model)
{
//Here,Post addmore value from view page and get multiple values from view page
return View();
}
}
}
After that create class HtmlHelper.cs use for "BeginCollectionItemCore" as above image highlight
BeginCollectionItemCore Must important for add more. Create New Class HtmlHelper.cs and past this code as given below
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using System.IO;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace HtmlHelpers.BeginCollectionItemCore
{
public static class HtmlPrefixScopeExtensions
{
private const string IdsToReuseKey = "__htmlPrefixScopeExtensions_IdsToReuse_";
public static IDisposable BeginCollectionItem(this IHtmlHelper html, string collectionName)
{
return BeginCollectionItem(html, collectionName, html.ViewContext.Writer);
}
public static IDisposable BeginCollectionItem(this IHtmlHelper html, string collectionName, TextWriter writer)
{
if (html.ViewData["ContainerPrefix"] != null)
collectionName = string.Concat(html.ViewData["ContainerPrefix"], ".", collectionName);
var idsToReuse = GetIdsToReuse(html.ViewContext.HttpContext, collectionName);
var itemIndex = idsToReuse.Count > 0 ? idsToReuse.Dequeue() : Guid.NewGuid().ToString();
string htmlFieldPrefix = $"{collectionName}[{itemIndex}]";
html.ViewData["ContainerPrefix"] = htmlFieldPrefix;
/*
* html.Name(); has been removed
* because of incorrect naming of collection items
* e.g.
* let collectionName = "Collection"
* the first item's name was Collection[0].Collection[<GUID>]
* instead of Collection[<GUID>]
*/
string indexInputName = $"{collectionName}.index";
// autocomplete="off" is needed to work around a very annoying Chrome behaviour
// whereby it reuses old values after the user clicks "Back", which causes the
// xyz.index and xyz[...] values to get out of sync.
writer.WriteLine($@"<input type=""hidden"" name=""{indexInputName}"" autocomplete=""off"" value=""{html.Encode(itemIndex)}"" />");
return BeginHtmlFieldPrefixScope(html, htmlFieldPrefix);
}
public static IDisposable BeginHtmlFieldPrefixScope(this IHtmlHelper html, string htmlFieldPrefix)
{
return new HtmlFieldPrefixScope(html.ViewData.TemplateInfo, htmlFieldPrefix);
}
private static Queue<string> GetIdsToReuse(HttpContext httpContext, string collectionName)
{
// We need to use the same sequence of IDs following a server-side validation failure,
// otherwise the framework won't render the validation error messages next to each item.
var key = IdsToReuseKey + collectionName;
var queue = (Queue<string>)httpContext.Items[key];
if (queue == null)
{
httpContext.Items[key] = queue = new Queue<string>();
if (httpContext.Request.Method == "POST" && httpContext.Request.HasFormContentType)
{
StringValues previouslyUsedIds = httpContext.Request.Form[collectionName + ".index"];
if (!string.IsNullOrEmpty(previouslyUsedIds))
foreach (var previouslyUsedId in previouslyUsedIds)
queue.Enqueue(previouslyUsedId);
}
}
return queue;
}
internal class HtmlFieldPrefixScope : IDisposable
{
internal readonly TemplateInfo TemplateInfo;
internal readonly string PreviousHtmlFieldPrefix;
public HtmlFieldPrefixScope(TemplateInfo templateInfo, string htmlFieldPrefix)
{
TemplateInfo = templateInfo;
PreviousHtmlFieldPrefix = TemplateInfo.HtmlFieldPrefix;
TemplateInfo.HtmlFieldPrefix = htmlFieldPrefix;
}
public void Dispose()
{
TemplateInfo.HtmlFieldPrefix = PreviousHtmlFieldPrefix;
}
}
}
}
- First,Want to create partial page "_AddMorePartialView "
- Open partial page "_AddMorePatialView" and past this code on this page as given below
@model AddMoreExample.Models.AddMoreViewModel
@{
Layout = null;
} @using HtmlHelpers.BeginCollectionItemCore;
@{ //BeginCollectionItemCore already created in HtmlHelper.cs class }
@using (Html.BeginCollectionItem("AddMoreList")) { <!-------"AddMoreList"----- this is AddMoreViewModel List Object wich is define ViewModel file --> <div id="removeAddMoreDiv" class="col-xs-12 col-sm-12 form-group"> <div class="row"> <div class="col-md-4"> <input asp-for="FirstName" placeholder="First Name" class="form-control" /> </div> <div class="col-md-4"> <input asp-for="LastName" placeholder="First Name" class="form-control" /> </div> <div class="col-md-4"> <button type="button" class="btn btn-danger btn-sm removeDiv"> Remove </button> </div> <div class="clearfix"></div> </div> </div> } <script> $(".removeDiv").click(function () { $(this).parents("#removeAddMoreDiv").remove(); }); </script>
Call partial page "_AddMorePatialView" from main page .So create first MainView page.
Open your Home Controller and Create new Page "MainView.cshtml".
Open your MainView.cshtml View page and past this code as given below .
<style> .form-group-material {
position: relative; margin-bottom: 0px !important; } </style> <script src="~/lib/jquery/dist/jquery.min.js"></script> <section class="forms"> <div class="container-fluid"> <div class="row"> <div class="col-lg-12"> <div class="card"> <div class="card-body"> <form asp-action="PostAddMore" class="text-left form-validate"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> <br /> <div class="col-sm-12"> @Html.Partial("_AddMorePartialView") </div> <div id="addAddMoreDiv"></div> <a id="add_row" class="btn btn-primary float-right"> Add Row</a> <br /> <br /> <input type="submit" class="btn btn-primary float-left" value="Save" /> </form> </div> </div> </div> </div> </div> </section> @section Scripts { <script> $('#add_row').on('click', function () { $.ajax({ url: '@Url.Action("AddMorePartialView", "Home")', type: 'GET', data: { }, success: function (result) { $('#addAddMoreDiv').append(result); }, error: function () { } }); }); </script> } @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
2 Comments
Rahul Sharma 3
Thank you so much.I have done my project by your blog.
Rahul Sharma 2
It's my pleasure