Search code examples
c#asp.net-mvcforms

How to retrieve all values from a from that can have unknown input field count


I have a simple form, that allows the user to edit a drop down list that exists within another form. In this the user can view the current drop down list values, edit them, delete them or create more values.

enter image description here

This opens this form in a modal:

enter image description here

Here you can edit existing values, delete them or add new:

enter image description here

So it can end up having any number of values!

The CSHTML for this:

@using (Html.BeginForm("EditDropDown", "Incidents", FormMethod.Post, new { onsubmit = "validateCustomTolerances()", id = "modal-form" }))
{
  @foreach (var opt in Model.IncRptOptions)
  {
    @if (opt.Type == "Action")
      {
        <div class="IncRpt-opt-modalDisp">
          <input type="text" id="" name="" value="@opt.TypeValue">
          <a class="edit-dropdown delete-existing"><i class="bi bi-trash3-fill"></i></a>
        </div>
      }
   }
   <div id="additional-options-here"></div>
   <a class="btn btn-sm btn-secondary" id="add-option">Add Option</a>
   <br>
   @*------ Hidden form content (required by controller action) ------*@
   <input id="optionType" type="hidden" name="optionType" value="Action" />

   @*------ Form buttons ------*@
   <div class="modal-form-btns">
     <button type="submit" class="btn btn-sm btn-primary modal-save-btn">Save</button>
     <button type="button" class="btn btn-sm btn-secondary">Cancel</button>
   </div>
}

The JS:

<script>
    // Deletes the existing option next to the 'bin' button user clicks it. 
    document.querySelectorAll('.delete-existing').forEach(item => {
        item.addEventListener('click', event => {
            let existingParent = item.parentElement;
            existingParent.remove();
        });
    });

    // Event listeners for the 'add option' button
    let addOption = document.querySelector('#add-option');

    // Creates the form input element for an additional option when button clicked
    addOption.addEventListener('click', function () {
        let parent = document.querySelector('#additional-options-here');
        let html = `
                <input type="text" id="test" name="" value="">
                <a class="edit-dropdown delete-added"><i class="bi bi-trash3-fill"></i></a>
                `;
        let template = document.createElement('div');
        template.setAttribute('class', 'IncRpt-opt-modalDisp')
        template.innerHTML = html;
        let finalHTML = template;
        finalHTML.querySelector('.delete-added').addEventListener('click', deleteAddedElement);
        parent.appendChild(finalHTML);
    });

    // Deletes the added option elements when user clicks on the 'bin' icons
    function deleteAddedElement() {
        let parent = this.parentElement;
        parent.remove();
    }
</script>

As a result, I do not know how many values will be returned.

Using Flask I used request.form.getList("Input-name-value"). What is the ASP.NET equivalent way of doing this?


Solution

  • So no one answered this, which is fine. Do not understand the down vote though! Anyway, I managed to fix this and so thought I would provide this below for future generations.

    I found that I could use the IFormCollection Interface and then use the the TryGetValue Method as in the below code. This then assigns the values from the form to StringValues that are able to be looped through.

    [HttpPost]
    public ActionResult EditDropDownList(IFormCollection collection, int ID)
    {
       if ((collection.TryGetValue("optionType", out StringValues LogTypes)) &&     (collection.TryGetValue("optionValue", out StringValues TypeValues)))
          {
             string logTypeText = string.Empty;
             string typeValueText = string.Empty;
             for (int i = 1; i <= TypeValues.Count; i++)
                {
                   logTypeText += LogTypes[i - 1] + ",";
                   typeValueText += TypeValues[i - 1] + ",";
                }
             }
    
       return RedirectToAction("RptPage", new RouteValueDictionary(new { Controller = "Home", Action = "Rpt", IncID = ID }));
    }