.Net 6 - Passing a radio button selected table row to a controller

Viewed 205

I really feel like this should be easy but I’m thinking it may have changed with .Net 6. I can pass values to my controller with the input “name=’name’” but for some reason I cannot get any values from my model into my controller. I am trying to POST my row values to the controller. I am using an enumerable. I’m not sure if I should be using a or not. Another thing is how should I be populating my table row from a loop of the model. I thought using @Html. Was for older .net and tag helpers are the new way but I couldn’t get any to work populating my rows.

<form method="post">
        <div id="tblPullParts" class="container justify-content-center mt-3">
       
            <table class="table table-striped">
           
                <thead>
                    <tr>
                        <th></th>
                        <th >Order #</th>
                        <th >Item</th>
                        <th >Description</th>
                        <th >Quantity</th>
                    </tr>
                </thead>
                <tbody>
                    @foreach (var p in Model)
                    {
                        <tr>
                            <td><input type="radio" id="radio" name="radio"
                                value="@Html.DisplayFor(item => p.PartID)" /></td>
@*<td><input asp-for="Selected" type="radio" value="Selected" /></td>*@
                            <th scope="row">@Html.DisplayFor(item => p.PartID)</th>
                            <td>@Html.DisplayFor(item => p.Name)</td>
                            <td>@Html.DisplayFor(item => p.ItemLocation)</td>
                            <td>@Html.DisplayFor(item => p.PartGroup)</td>
                            <td>@Html.DisplayFor(item => p.Description)</td>
                            <td>
                                <input type="text" asp-for="@p.Name" id="txtNameN" />
                            </td>
                        </tr>
                    }
                    
                </tbody>

            </table>         
            @*<input type="text" id="@Model[0].Name" />*@
            <input type="text" id="txtName" name="txtName" value="" />
        </div>
        <div class="text-center">
            <button type="submit" class="btn btn-lg btn-success mt-3">Start Pick</button>

        </div>
     </form>

[HttpPost]
        public async Task<IActionResult> Index( PartVM model, string radio, string txtName)
        {
            
            if (model?.PartID != 0)
            {
                return View("UpdatePickQuantity", model);
            }

            if (!String.IsNullOrWhiteSpace(txtName))
            {

            }

            //Request.QueryString["radio"];
            var lstParts = await _ordersService.GetAllParts();

            return View(lstParts);
        }
2 Answers

@Html.DisplayFor() can only display the value of model, If you want to submit the value, You need to use <input>,Here is a simple demo, I add hidden input in your form to submit the value:

@model List<PartVM>
@{
    int i = 0;
}

    <form method="post">
        <div id="tblPullParts" class="container justify-content-center mt-3">
       
            <table class="table table-striped">
           
                <thead>
                    <tr>
                        <th></th>
                        <th >Order #</th>
                        <th >Item</th>
                        <th >Description</th>
                        <th >Quantity</th>
                    </tr>
                </thead>
                <tbody>
                    
                    @foreach (var p in Model)
                    {
                    
                    <tr>
                        <td><input type="radio" id="radio" name="radio"
                                value="@Html.DisplayFor(item => p.PartID)" /></td>
@*<td><input asp-for="Selected" type="radio" value="Selected" /></td>*@
                            <th scope="row">
                                @Html.DisplayFor(item => p.PartID)
                                <input type="hidden"  asp-for="@p.PartID" name="[@i].PartID">
                            </th>                                                
                            <td>
                                @Html.DisplayFor(item => p.Name)
                                
                            </td>
                           
                            <td>
                                @Html.DisplayFor(item => p.ItemLocation)
                                <input type="hidden"  asp-for="@p.ItemLocation" name="[@i].ItemLocation">
                            </td>
                            
                            <td>
                                @Html.DisplayFor(item => p.PartGroup)
                                <input type="hidden"  asp-for="@p.PartGroup" name="[@i].PartGroup">
                            </td>
                            
                            <td>
                                @Html.DisplayFor(item => p.Description)
                                <input type="hidden"  asp-for="@p.Description" name="[@i].Description">
                            </td>
                            <td>
                                <input type="text" asp-for="@p.Name"  name="[@i].Name" id="txtNameN" />
                            </td>                         
                    </tr>
                    i++;
                }
                    
                </tbody>

            </table>         
            @*<input type="text" id="@Model[0].Name" />*@
            <input type="text" id="txtName" name="txtName" value="" />
        </div>
        <div class="text-center">
            <button type="submit" class="btn btn-lg btn-success mt-3">Start Pick</button>

        </div>
 </form>

Controller

    [HttpPost]
    public async Task<IActionResult> Index( List<PartVM> model, string radio, string txtName)
    {

         //.....
    }

Demo:

enter image description here

Your second question can refer to this github issue.

Edit============================

If you want just want to pass the row where radio is selected, you need to js to achieve this. refer to this:

Create a ViewModel

public class PartvmViewModel
{
    public int PartID { get; set; }
    public string Name { get; set; }
    public string ItemLocation { get; set; }
    public string PartGroup { get; set; }
    public string Description { get; set; }
    public string? txtName { get; set; }
}

controller

public IActionResult Display()

{
    List<PartvmViewModel> viewmodel = new List<PartvmViewModel>();

//pass data from PartVM to PartvmViewModel
    foreach (var item in PartVms)
    {
        viewmodel.Add(new PartvmViewModel()
        {
            PartID = item.PartID,
            Description = item.Description,
            ItemLocation = item.ItemLocation,
            Name = item.Name,
            PartGroup = item.PartGroup
        });
    }
    return View(viewmodel);
}


[HttpPost]
public IActionResult Display([FromBody]PartvmViewModel model)
{
      //because the value of radio is equal to PartID,SO i don't write it as parameter here
      //.........
            
}

View

@model List<PartvmViewModel>
@{
    int i = 0;
}

<form method="post">
    <div id="tblPullParts" class="container justify-content-center mt-3">
       
        <table class="table table-striped">
           
            <thead>
            <tr>
                <th></th>
                <th >Order #</th>
                <th >Item</th>
                <th >Description</th>
                <th >Quantity</th>
            </tr>
            </thead>
            <tbody>
                    
            @foreach (var p in Model)
            {
                    
                <tr>
                    <td><input type="radio"  name="radio" onclick="Method(this)" 
                               value="@Html.DisplayFor(item => p.PartID)" /></td>
                    @*<td><input asp-for="Selected" type="radio" value="Selected" /></td>*@
                    <th scope="row">
                        @Html.DisplayFor(item => p.PartID)
                        <input type="hidden"  asp-for="@p.PartID" name="[@i].PartID" id="PartID">
                    </th>                                                
                    <td>
                        @Html.DisplayFor(item => p.Name)
                                
                    </td>
                           
                    <td>
                        @Html.DisplayFor(item => p.ItemLocation)
                        <input type="hidden"  asp-for="@p.ItemLocation" name="[@i].ItemLocation" id="ItemLocation">
                    </td>
                            
                    <td>
                        @Html.DisplayFor(item => p.PartGroup)
                        <input type="hidden"  asp-for="@p.PartGroup" name="[@i].PartGroup" id="PartGroup">
                    </td>
                            
                    <td>
                        @Html.DisplayFor(item => p.Description)
                        <input type="hidden"  asp-for="@p.Description" name="[@i].Description" id="Description">
                    </td>
                    <td>
                        <input type="text" asp-for="@p.Name"  name="[@i].Name" id="txtNameN" />
                    </td>                         
                </tr>
                i++;
            }
                    
            </tbody>

        </table>         
        @*<input type="text" id="@Model[0].Name" />*@
        <input type="text" id="txtName" name="txtName" value="" />
    </div>
    <div class="text-center">
        <button  class="btn btn-lg btn-success mt-3" onclick="Submit()">Start Pick</button>

    </div>
</form>

@section Scripts
{
    <script>
    
    var Data;
    
        function Method(obj){
            
            
             this.Data = {
                
                "PartID":$(obj).val(),
                
                "ItemLocation" : $(obj).parent().parent().find('td:eq(2)').find(':input').val(),
                
                "PartGroup" : $(obj).parent().parent().find('td:eq(3)').find(':input').val(),
                
                "Description" : $(obj).parent().parent().find('td:eq(4)').find(':input').val(),
                
                 "Name" : $(obj).parent().parent().find('td:eq(4)').find(':input').val(),
            }        
        }
        
        function Submit(){          
            Data.txtName = $("#txtName").val();           
           $.ajax({
                url : '/Home/Display',
                type : 'post',
                data : JSON.stringify(Data),
                contentType : 'application/json'
           });
        }
    </script>
}

My opinion==========================

Actually, In my opinion, Pass the list of data is ok. Because i notice that you pass the value of radio into the controller, You can just use:

[HttpPost]
    public async Task<IActionResult> Index( List<PartVM> model, string radio, string txtName)
    {
     
        var item = model.Where(i => i.PartID == int.Parse(radio)).FirstOrDefault();
         //.....
    }

to get the selected row, It is more easier than using js;

Instead of doing this

<th scope="row">
    @Html.DisplayFor(item => p.PartID)
   <input type="hidden"  asp-for="@p.PartID" name="[@i].PartID" id="PartID">
</th>    

I would do something like

<th scope="row">
  <p>@p.PartID</p>
  <input type="hidden"  asp-for="@p.PartID" name="[@i].PartID" id="PartID">
</th>    

However, I could be wrong because you are using razor syntax and I am not use to that yet ;)

Related