2

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>

1 Answer 1

5

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.