3

In my app I want to make model that can have dynamic list of attributes:

Provider class

using System;
using System.Collections.Generic;

namespace DynamicForms.Models
{
    public class Provider
    {
        public String Name { get; set; }
        public List<Attribute> Attributes { get; set; }

        public Provider()
        {
            Attributes = new List<Attribute>();
        }
    }
}

My controller has two methods. One to add more attributes to current model and one to save Provider model. Method to add more attributes looks like this:

    [HttpPost]
    // Add attribute to current provider model
    public IActionResult Index(Provider provider)
    {
        provider.Attributes.Add(new Models.Attribute());
        return View(provider);
    }

And my view looks like this:

@model Provider
@using (Html.BeginForm())
{
    <div>
        @Html.TextBoxFor(m => m.Name)
        <input type="submit" value="Add attribute" formmethod="post"/>
    </div>
    <div>
        @foreach ( var attribute in Model.Attributes)
        {
        <div>
            @Html.TextBoxFor(a => attribute.Name)
            @Html.TextBoxFor(a => attribute.Value)
        </div>
        }
    </div>
    <div>
        <input type="submit" value="Save form" formaction="Provider/Save" formmethod="post"/>
    </div>
}

When I press "Add attribute" button attribute is added and a row of input fields is appearing. However when i press the button one more time nothing happens. No another row is added. Model attributes count is still 1. I've been looking for solutions all over the web but couldn't find anything that fixes my problem. How can I make form fields be added dynamically to model and displayed in vieW?

2 Answers 2

4

Try looping over your List with an index instead of foreach, e.g.

@for (var i = 0; i < Model.Attributes.Count; i++)
{
  <div>
    @Html.TextBoxFor(a => Model.Attributes[i].Name)
    @Html.TextBoxFor(a => Model.Attributes[i].Value)
  </div>
}

You want the names to be formatted something like this Attributes[0].Name, etc.

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

2 Comments

Wow, this works just like that. Thank you so much. But why foreach wasn't working in this case? Can you explain it somehow?
@Kamilton because if you bind with the variable name the index doesn't make it into the name and the model binding doesn't make it into an array. Try to do a ViewSource and see what the names are and it will make sense.
-2

You wrote a method for Post, but you wrote a method for get.

Get method

   public IActionResult Index()
    {
        Provider provider = new Provider();
        provider.Attributes.Add(new Models.Attribute());
        return View(provider);
    }

Post metod

   [HttpPost]
    // Add attribute to current provider model
    public IActionResult Index(Provider provider)
    {
        provider.Attributes.Add(new Models.Attribute());
        return View(provider);
    }

1 Comment

What do you mean by that? I also have a get method but that's not significant in that case, isn't it?

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.