-1

I want user to be able to add or remove the controls dynamically on form. User may have multiple addresses. So I have created a List of CommunicationDetailsViewmodel. The CommunicationDetailsViewmodel is as follow:

public class CommunicationDetailsViewModel
    {
        public string OrganizationName { get; set; }
        public List<Country> Country { get; set; }

        public List<State> State { get; set; }

        public List<City> City { get; set; }

        [Display(Name = "Id")]
        public int CountryId { get; set; }

        [Display(Name = "Id")]
        public int StateId { get; set; }

        [Display(Name = "Id")]
        public int CityId { get; set; }

        [StringLength(32), Required(ErrorMessage = "Address is required")]
        public string Address { get; set; }
    }

The SupplierInformationViewmodel is as below:

public class SupplierInformationViewModel
{
    public SupplierInformationViewModel()
    {
        CommunicationDetailsViewModel = new List<ViewModels.CommunicationDetailsViewModel>();
    }

    [StringLength(50, ErrorMessage = "Organization name cannot be greater than 50 characters"), Required(ErrorMessage ="Organization name is required")]
    public string OrganizationName { get; set; }

    public List<CommunicationDetailsViewModel> CommunicationDetailsViewModel { get; set; }
}

The view is as below:

@model WebAPI.ViewModels.SupplierInformationViewModel
@{
    ViewBag.Title = "Supplier Information";
}

<h4>Supplier Details</h4>

@using (Html.BeginForm("Save", "SupplierInformation", FormMethod.Post))
{
    <div class="demo-section k-content">
        <div class="form-group">
            @Html.Label("Organization name")
            @Html.Kendo().TextBoxFor(model => model.OrganizationName).Name("OrganizationName").HtmlAttributes(new { @class = "k-textbox required", placeholder = "Organization Name" })
        </div>

        @for (int i = 0; i < Model.CommunicationDetailsViewModel.Count; i++)
        {
            <div class="form-group">
                @Html.Label("Country")
                @(Html.Kendo().DropDownListFor(model => model.CommunicationDetailsViewModel[i].CountryId).DataTextField("CountryName").DataValueField("Id").BindTo(Model.CommunicationDetailsViewModel[i].Country))
            </div>
            <div class="form-group">
                @Html.Label("State")
                @(Html.Kendo().DropDownListFor(model => model.CommunicationDetailsViewModel[i].StateId).DataTextField("StateName").DataValueField("Id").BindTo(Model.CommunicationDetailsViewModel[i].State))
            </div>
            <div class="form-group">
                @Html.Label("City")
                @(Html.Kendo().DropDownListFor(model => model.CommunicationDetailsViewModel[i].CityId).DataTextField("CityName").DataValueField("Id").BindTo(Model.CommunicationDetailsViewModel[i].City))
            </div>
            <div class="form-group">
                @Html.Label("Address")
                @Html.Kendo().TextBoxFor(model => model.CommunicationDetailsViewModel[i].Address).Name("Address").HtmlAttributes(new { @class = "k-textbox required", placeholder = "Address", @maxlength = "32" })
            </div>
            <div class="form-group">
                @Html.Label("Building name")
                @Html.Kendo().TextBoxFor(model => Model.CommunicationDetailsViewModel[i].BuildingName).Name("BuildingName").HtmlAttributes(new { @class = "k-textbox required", placeholder = "Address", @maxlength = "32" })
            </div>
        }
        <input type="button" value="Add New Address" />
    </div>
    @Html.Kendo().Button().Name("btnSave").Content("Save").HtmlAttributes(new { type = "submit", @class = "k-button k-primary" })
}

On Add New Address button click, I want to generate fields like Country dropdown, State dropdown, City dropdown with the values and expty textboxes for Building Name, Address, etc. When user posts this form, all these newly added fields should get posted. These fields are part of the CommunicationDetailsViewModel. So, in my action, I should be able to get exisiting as well as newly added fields.

Any idea how can I achieve this?

Lokesh
  • 137
  • 2
  • 12
  • Refer [Submit same Partial View called multiple times data to controller](https://stackoverflow.com/questions/28019793/submit-same-partial-view-called-multiple-times-data-to-controller/28081308#28081308) for some options and [A Partial View passing a collection using the Html.BeginCollectionItem helper](http://stackoverflow.com/questions/40539321/partial-view-passing-a-collection-using-the-html-begincollectionitem-helper/40541892#40541892) for a detailed implementation using `BeginCollectionItem` –  Oct 24 '18 at 11:58

1 Answers1

1

Razor on its own is not very good at manipulating the DOM in this sense. Your best bet is to use some JavaScript or jQuery to get the effect you are looking for. Personally I would create the fields in razor but set up the styles so they are hidden by default. You can then attach a click handler to your Add New Address button, which would call a function to change the styles of the inputs to display them. You could even add and remove validation logic from the fields using jQuery if you need validation messages. However, if you want to allow for as many new addresses as the user desires, this method will not work very well. In that case your JS add new address function would have to dynamically add new fields to the form, instead of just showing the hidden ones. Hope this was helpful!

E McG
  • 279
  • 1
  • 8
  • I also think that creating fields and setting their style as hidden is good option. I will have to confirm with the client at max how many addresses is he going to add. But now question is how to post the values of all these controls to action? Will these values be part of the `CommunicationDetailsViewModel`? – Lokesh Oct 25 '18 at 05:05