Home > Enterprise >  ASP.NET Core : creating form input for model property of type List
ASP.NET Core : creating form input for model property of type List

Time:11-07

I have been searching online for an answer to this specific issue but I can't seem to find it.

I am currently creating a form using Razor pages and cannot find out how to create a form input that would be able to take multiple values for one item in the form. Below I will post a quick example of what I mean.

Current issues: when I add another input programmatically it will only add 2 maximum and will not send a value

Model:

public class FormInput 
{
    public List<Address> Addresses { get; set; }
    public List<Category> Categories { get; set; }
}

Razor Page:

public class FormPage : PageModel
{
    [BindProperty] public FormInput _Input { get; set; }
}

HTML Page:

<form>
    <ul class="Category-Container">
      <li>
        <input asp-for="_Input.Addresses" type="text" />
        <button type="button" onclick="this.AddCategory">
        Add New Address
        </button>
      </li>
    </ul>
    <div>
        <input asp-for="_Input.Categories" type="text" />
        <button type="button" onclick="this.AddNewInput">
        Add New Category
        </button>
    </div>
</form>

Javascript:

var categoryContainer = document.getElementById("Category-Container");

 function AddCategory() {

        var input = document.createElement("input");
        input.classList.add("w-100");
        input.name = "BusinessCategory";
        var inputCol = document.createElement("div");
        inputCol.classList.add("col-8");
        inputCol.appendChild(input);

        var btn = document.createElement("button");
        btn.classList.add("btn");
        btn.classList.add("btn-primary");
        btn.innerText = "Add New Category";
        var btnCol = document.createElement("div");
        btnCol.classList.add("col");
        btnCol.appendChild(btn);

        var row = document.createElement("li");
        row.classList.add("row");
        var part1 = row.appendChild(inputCol);
        var part2 = part1.appendChild(btnCol);

        categoryContainer.appendChild(part2);
    }

There's a little disconnect in the javascript function but you can assume that the Button and the Input in the HTML example are inside of Columns also, i don't think that makes a big difference but please let me know if it would be one

CodePudding user response:

Tag helper cannot pass complex model type data to backend, it only allows simple type. That is to say, you need set the model's property name in asp-for.

Then, if you want to get the list model, you need specific the list index like: _Input.Categories[0].PropertyName.

Not sure what is your whole view, here is a simple demo about how to pass list model to backend:

Model:

public class FormInput
{
    public List<Address> Addresses { get; set; }
    public List<Category> Categories { get; set; }
}
public class Address
{
    public string Name { get; set; }
}
public class Category
{
    public string BusinessCategory { get; set; }
}

View:

@page
@model IndexModel
<form method="post">
    <ul id="Category-Container">
        <li>
            <input asp-for="_Input.Categories[0].BusinessCategory" type="text" />
            <button type="button" onclick="AddCategory()">
                Add New Address
            </button>
        </li>
    </ul>
    <div>
        <input asp-for="_Input.Addresses[0].Name" type="text" />
        <button type="button" onclick="this.AddNewInput">
            Add New Category
        </button>
    </div>
    <input type="submit" value="Post"/>
</form>

JS:

@section Scripts
{
<script>
    var count = 1;  //add count...
    var categoryContainer = document.getElementById("Category-Container");

    function AddCategory() {

        var input = document.createElement("input");
        input.classList.add("w-100");
   //change the name here.....
        input.name = "_Input.Categories[" count "].BusinessCategory";
        var inputCol = document.createElement("div");
        inputCol.classList.add("col-8");
        inputCol.appendChild(input);

        var btn = document.createElement("button");
        btn.classList.add("btn");
        btn.classList.add("btn-primary");
        btn.innerText = "Add New Category";
        var btnCol = document.createElement("div");
        btnCol.classList.add("col");
        btnCol.appendChild(btn);

        var row = document.createElement("li");
        row.classList.add("row");
        var part1 = row.appendChild(inputCol);
        part1.appendChild(btnCol); //change here...

        categoryContainer.appendChild(part1);  //change here...
        count  ;  //add here ...
    }
</script>
}

Backend code:

public class IndexModel: PageModel
{
    [BindProperty] public FormInput _Input { get; set; }

    public IActionResult OnGet()
    {

        return Page();
    }
    public void OnPost()
    {

    }
}
  • Related