Reputation:
I have a similar problem to this question in that I cannot get a Blazor EditForm to bind to a simple List.
Am I missing something in order to bind a List to an EditForm?
Person.cs
public class Person {
public List<string>? Names { get; set; }
}
EditForm1.razor produces a compile-time error: Cannot assign to 'item' because it is a 'foreach iteration variable'
. I get that - the iterator is read-only so I can understand that.
<EditForm Model="@person">
@if (person is not null) {
@if (person.Names is not null) {
@foreach (var item in person.Names) {
<InputText @bind-Value="@item" />
}
}
}
</EditForm>
So, as per the referenced Microsoft documentation I refactored it.
EditForm2.razor compiles and runs... until person.Names actually has a value. It then throws ArgumentException: The provided expression contains a InstanceMethodCallExpression1 which is not supported. FieldIdentifier only supports simple member accessors (fields, properties) of an object. Microsoft.AspNetCore.Components.Forms.FieldIdentifier.ParseAccessor<T>(Expression<Func<T>> accessor, out object model, out string fieldName)
<EditForm Model="@person">
@if (person is not null) {
@if (person.Names is not null) {
@for (int x = 0; x < person.Names.Count; x++) {
<InputText @bind-Value="@person.Names[x]" />
}
}
}
</EditForm>
EditForm3.razor is my last attempt. This compiles and renders, but as soon as I try and do anything with the edit box the app crashes with Unhandled exception rendering component: Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')
. I'm 99% sure this approach is wrong but I am now clutching at straws.
<EditForm Model="@person">
@if (person is not null) {
@if (person.Names is not null) {
@for (int x = 0; x < person.Names.Count; x++) {
<input @bind="@person.Names[x]" />
}
}
}
</EditForm>
Upvotes: 2
Views: 3440
Reputation: 45764
The answer is in the accepted answer you linked to...
You are looking to create a two-way data binding of a collection.
<EditForm Model="@person">
@foreach (var PName in person.names)
{
<InputText @bind-Value="@PName.Name" />
}
</EditForm>
@code
{
private Person person = new Person {ID = "1", names = new List<PersonName>()
{ new PersonName {Name = "Marry" },
new PersonName {Name = "Marria" }
};
public class Person
{
public string ID {get;set;}
public List<PersonName> names { get; set; }
}
public class PersonName
{
public string Name { get; set; }
}
}
Note that in order to bind the Name property, you must define it in a class of its own, and in the Person model you define a list of that class ( PersonName ). This is the only way to bind to a collection.
Upvotes: 5