Using Html.TextBoxFor in a For Each Loop

Kmcnet 966 Reputation points
2023-07-23T02:07:51.9866667+00:00

Hello everyone and thanks for the help in advance. I want to create a MVC view that accepts a list of element names and then creates input textboxes from the list. Something like this:

@foreach (var item in Model) {@Html.TextBoxFor(m => item.ElementName, new { @placeholder = item.DisplayName}) }

I am having problems controlling the element name and placeholder values for each of the elements created. Does anyone have experience doing something like this and can it be used viably? I am able to create the elements using standard HTML within the foreach loop, but the helpers may be advantageous.

ASP.NET
ASP.NET
A set of technologies in the .NET Framework for building web applications and XML web services.
3,595 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
11,296 questions
{count} votes

Accepted answer
  1. Lan Huang-MSFT 30,176 Reputation points Microsoft Vendor
    2023-07-26T07:48:03.86+00:00

    Hi @Kmcnet,

    I think I misunderstood your needs in the first place. If you want to dynamically create name and placeholder value for each element.

    You can use Html.TextBox instead.

    User's image

    @model List<MvCoreDemo.Models.tbl_Log_FormFields>
    
    
    <h1>Index</h1>
    @for (var i = 0; i < Model.Count(); i++)
    {
    
        @Html.TextBox(Model[i].ElementName, Model[i].ElementName, new { id = Model[i].ElementName, placeholder = Model[i].DisplayName })
    }
    
     public IActionResult Index()
            {
                List<tbl_Log_FormFields> formFields = new List<tbl_Log_FormFields>();
                formFields.Add(new tbl_Log_FormFields() {
                    DisplayName = "Display Name", 
                    ElementName = "FirstName" });
    
                return View(formFields);
            }
    
    public class tbl_Log_FormFields { 
            public int ID { get; set; } 
            public string? DisplayName { get; set; } 
            public string? ElementName { get; set; } 
        }
    

    enter image description here

    Best regards,
    Lan Huang


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


2 additional answers

Sort by: Most helpful
  1. Bruce (SqlWork.com) 71,506 Reputation points
    2023-07-23T03:18:33.53+00:00

    simple:

    @for (var i=0; i < Model.Count(); ++i) 
    {
       @Html.TextBoxFor(m => Model[i].ElementName, new {placeholder = Model[i].DisplayName}) 
    }
    

    you don't the models datatype so it be .Count or .Length, instead of .Count()

    0 comments No comments

  2. AgaveJoe 1,505 Reputation points
    2023-07-25T17:57:38.73+00:00

    So basically, the helper in this situation is no help whatsover from what I can see.

    HTML helpers are designed to work with standard MVC model binding where the model property name matches the input name.

    As far as I can tell, you are trying to create a form builder. The design is an generic abstraction where the input name is a property value not the property name. Therefore you must build another abstraction to bind the data. Below is an example based on your code sample.

        public class tbl_Log_FormFields
        {
            public int ID { get; set; }
            public string? DisplayName { get; set; }
            public string? ElementName { get; set; }
        }
    
        public class FormFieldInput
        {
            public int ID { get; set; }
            public string? Value { get; set; }
            public string? ElementName { get; set; }
    
        }
    
        public class DynamicFieldsController : Controller
        {
            [HttpGet]
            public IActionResult Index()
            {
                List<tbl_Log_FormFields> formFields = new List<tbl_Log_FormFields>();
                formFields.Add(new tbl_Log_FormFields()
                {
                    Id = 1,
                    DisplayName = "First Name",
                    ElementName = "FirstName"
                });
                formFields.Add(new tbl_Log_FormFields()
                {
                    Id = 2,
                    DisplayName = "Last Name",
                    ElementName = "LastName"
                });
    
                return View(formFields);
            }
    
            [HttpPost]
            public IActionResult Index(List<FormFieldInput> values)
            {
                return Json(values);
            }
        }
    
    @model List<MvcDemo.Models.tbl_Log_FormFields>
    @{
        ViewData["Title"] = "Index";
    }
    
    <h1>Index</h1>
    <div>
        <form method="post">
            @for(int i=0; i<Model.Count(); i++)
            {
                <div>
                    <label>@Model[i].DisplayName</label>
                    <input type="hidden" name='@($"[{i}].ID")' value="@Model[i].ID" />
                    <input type="text" name='@($"[{i}].Value")' placeholder="@Model[i].DisplayName" />
                    <input type="hidden" name='@($"[{i}].ElementName")' value="@Model[i].ElementName" />
                </div> 
            }
            <div>
                <input type="submit" value="submit" />
            </div>
        </form>
    </div>
    

    Results example

    [
      {
        "id": 1,
        "value": "hello",
        "elementName": "FirstName"
      },
      {
        "id": 2,
        "value": "world",
        "elementName": "LastName"
      }
    ]
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.