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()
{
}
}