Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create dynamic forms that grow at run time

I'm working in asp.net core inside a MVC application. I'm using the scaffolding feature that creates the views and controller based on a model. Below is the model that i'm using:

class ShoppingList
{
    public int ShoppingListId { get; set; }
    public string Name { get; set; }
    public List<string> ListItems { get; set; }            
}

The form that displays to the user via the view only displays the field for Name. I would like the form to be able to show a field for a list item, and then if the user wants to add another list item they can hit a button to add another field to do so. They at run time decide how many shopping list items they want to add.

Here is the razor cshtml form i'm using:

<form asp-action="Create">
     <div asp-validation-summary="ModelOnly" class="text-danger"></div>
        <div class="form-group">
           <label asp-for="Name" class="control-label"></label>
           <input asp-for="Name" class="form-control" />
           <span asp-validation-for="Name" class="text-danger"></span>
        </div>
     <div class="form-group">
     <input type="submit" value="Create" class="btn btn-default" />
     </div>
</form>

Is there an easy way to do this? I don't want to have to hard code a number.

like image 890
conterio Avatar asked Oct 20 '17 17:10

conterio


People also ask

How do you build a dynamic form at run time?

The proper method to create dynamic forms at runtime is to add controls to and remove them from your form as needed, using the techniques discussed in this section. Just as you can create new instances of forms, you can also create new instances of any control and place them on a form.

How do you dynamically submit a form?

Answer: Use the jQuery submit() Method You can use the submit() method to submit an HTML form (i.e. ) using jQuery. The jQuery code in the following example will submit the form on click of the button (i.e. the element) which has the type attribute set to button (i.e. type=”button” ).

Can Google Forms be dynamic?

Dynamic Fields Add-on for Google Forms™ populates values of selection fields. Questions of type Multiple-choice, Drop-down, Checkbox or Grid can be updated by data from Sheets, Contacts or Groups. Create in Google Forms™ dynamic choice boxes.


1 Answers

If you want to allow the user to add a new form element on the client side you need to use javascript to update the DOM with the new element you want to add. To list the existing items you may use editor templates. Mixing these 2 will give you a dynamic form. The below is a basic implementation.

To use editor templates, we need to create an editor template for the property type. I would not do that for string type which is more like a generic one. I would create a custom class to represent the list item.

public class Item
{
    public string Name { set; get; }
}
public class ShoppingList
{
    public int ShoppingListId { get; set; }
    public string Name { get; set; }
    public List<Item> ListItems { get; set; }

    public ShoppingList()
    {
        this.ListItems=new List<Item>();
    }
}

Now, Create a directory called EditorTemplates under ~/Views/YourControllerName or ~/Views/Shared/ and create a view called Item.cshtml which will have the below code

@model  YourNameSpaceHere.Item
<input type="text" asp-for="Name" class="items" />

Now in your GET controller, create an object of the ShoppingList and send to the view.

public IActionResult ShoppingList()
{
    var vm = new ShoppingList() {  };
    return View(vm);
}

Now in the main view, All you have to do is call the EditorFor method

@model YourNamespace.ShoppingList
<form asp-action="ShoppingList" method="post">
    <input asp-for="Name" class="form-control" />
    <div class="form-group" id="item-list">
        <a href="#" id="add">Add</a>
        @Html.EditorFor(f => f.ListItems)
    </div>
    <input type="submit" value="Create" class="btn btn-default" />
</form>

The markup has an anchor tag for adding new items. So when user clicks on it, we need to add a new input element with the name attribute value in the format ListItems[indexValue].Name

$(function () {

   $("#add").click(function (e) {
       e.preventDefault();
       var i = $(".items").length;
       var n = '<input type="text" class="items" name="ListItems[' + i + '].Name" />';
       $("#item-list").append(n);
   });

});

So when user clicks it adds a new input element with the correct name to the DOM and when you click the submit button model binding will work fine as we have the correct name attribute value for the inputs.

[HttpPost]
public IActionResult ShoppingList(ShoppingList model)
{
    //check model.ListItems
    // to do : return something
}

If you want to preload some existing items (for edit screen etc), All you have to do is load the ListItems property and the editor template will take care of rendering the input elements for each item with correct name attribute value.

public IActionResult ShoppingList()
{
    var vm = new ShoppingList();
    vm.ListItems = new List<Item>() { new Item { Name = "apple" } }
    return View(vm);
}
like image 84
Shyju Avatar answered Oct 26 '22 07:10

Shyju