Search code examples
javascriptjqueryasp.net-mvcwebgrid

Grid row selection in mvc view


In my MVC application, I am using a webgrid to display user details in the view. In each row it has a column with a radio button to select that row.

In the same view it has a form also. If the user selecting a row by clicking on the radio button, then the corresponding details should fill in the form control. Then the user can edit the details from that form.

How can i filter a particular user details based on the row id and fill it in the form? Can I use LINQ in jQuery function for this?

This is my View,

@model IEnumerable<MyTestProject.Models.modeldata>
@{
    Layout = null;
    WebGrid grid = new WebGrid(Model, rowsPerPage: 5,selectionFieldName:"SelectedRow");
}
<link href="@Url.Content("~/Content/jquery-ui.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-1.10.2.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery-ui-1.11.4.min.js")" type="text/javascript"></script>

<!DOCTYPE>
<style type="text/css">
    .gridTable {margin: 5px;padding: 10px;border: 1px #c8c8c8 solid;border-collapse: collapse;min-width: 550px; background-color: #fff;color: #fff;}
.gridHead th{font-weight: bold;background-color: #030D8D;color: #fff;padding: 10px}
.gridHead a:link,.gridHead a:visited,.gridHead a:active,.gridHead a:hover {color: #fff;}
.gridHead a:hover {text-decoration:underline;}
.gridTable tr.gridAltRow{background-color: #efeeef;}
.gridTable tr:hover{background-color: #f6f70a;}
.gridAltRow td{padding: 10px;margin: 5px; color: #333;}
.gridRow td{padding: 10px;color: #333;}
.gridFooter td{padding: 10px; background-color: #c7d1d6;color: #999;font-size: 12pt;text-align: center;}
.gridFooter a{font-weight: bold;color: #333; border: 1px #333 solid;}
</style>
<html>
    <head runat="server">
        <title>EDIT with Grid</title>
    </head>
<body style="padding:10px">
        <div>
<div> 
                @grid.GetHtml(
    tableStyle: "table",
    fillEmptyRows: false,
    headerStyle: "header",

    footerStyle: "grid-footer",

    mode: WebGridPagerModes.All,
    firstText: "<< First",
    previousText: "< Prev",
    nextText: "Next >",
    lastText: "Last >>",

    columns: new[]  // colums in grid
    {
        grid.Column(header: "Select", format: @<text><input name="chck" type="RADIO" id="chck" class="rbutton" value="@item.id" /></text>),
        grid.Column("name"  ),
        grid.Column("age"),
        grid.Column("email"),
        grid.Column("mob"),
   })
            </div>
<form>
                <h2>Edit User Details</h2>
                <div class="space">
                    <div>Name</div>
                    <div>@Html.TextBox("txtname")</div>
                </div>
                <div class="space">
                    <div>Age</div>
                    <div>@Html.TextBox("txtage")</div>
                </div>
                <div class="space">
                    <div>Email</div>
                    <div>@Html.TextBox("txtmail")</div>

                </div>
                <div class="space">
                    <div>Mobile</div>
                    <div>@Html.TextBox("txtmob")</div>
                </div>
                <div style="margin-top:20px">
                    <input type="submit" id="ButtonSave" value="Save" />
                </div>
</form>
</div>
    </body>
    </html>

<script type="text/javascript">

    $('.rbutton').click(function () {
        try
        {
            var row = $(this).closest('tr');
            $('#txtname').val(row.children('td').eq(1).text());
        }
        catch(ex)
        {
            alert(ex.message);
        }
    });


</script> 

And, my model class is,

public class modeldata
    {
        public int id { get; set; }
        public string name { get; set; }
        public string age { get; set; }
        public string email { get; set; }
        public string mob { get; set; }
    }

And finally the controller is,

public ActionResult EditUser()
        {
            List<modeldata> lmd = new List<modeldata>();
            DataTable dt = Db.GetUserDetails();
            foreach(DataRow dr in dt.Rows)
            {
                lmd.Add(new modeldata
                {
                    id = Convert.ToInt32(dr["ID"]),
                    name = dr["Name"].ToString(),
                    age = dr["Age"].ToString(),
                    email = dr["Email"].ToString(),
                    mob = dr["Mobile"].ToString()
                });
            }
            return View(lmd);
        }

Solution

  • One option is to add the values of you model to the radio button as data- attributes and read then in the script.

    Change the html for the button to

    <input type="radio" name="chck" class="radiobutton" data-name="@item.name" data="@item.age" ..... />
    

    and in the script

    $('.radiobutton').change(function() {
      $('#txtname').val($(this).data('name'));
      $('#txtage').val($(this).data('age'));
      ....
    });
    

    Another is to use relative selectors to read the values from the table cells in the associated columns. You have not shown the actual html generated by you code, so the following may need to modified to suit

    <input type="radio" name="chck" class="radiobutton" />
    

    Script

    $('.radiobutton').change(function() {
      var row = $(this).closest('tr'); // get the associated row
      $('#txtname').val(row.find('td').eq(1).text()); // get the text of the 2nd cell in the row
      ....
    });
    

    Note the following with regards to the above code:

    1. Remove your id attribute from the radio button - your generating duplicate id attributes which is invalid html
    2. Remove the onclick attribute (don't pollute you markup with behavior) and use Unobtrusive Javascript

    I also recommend you change the way you are generating the form to make use of model bind and allow client and server side validation

    Create a partial view (say) _UserData.cshtml

    @model modeldata
    <form id="userform">
        @Html.LabelFor(m => m.name)
        @Html.TextBoxFor(m => m.name)
        @Html.ValidationMessageFor(m => m.name)
        .... // elements for other properties
        <button id="save" type="button">Save</button>
    </form>
    

    And in the main view use

    @Html.Partial("_UserData")
    

    And assuming your submitting using ajax so that you can edit multiple users without leaving the page, the script in the main view would be

    var url = '@Url.Action("Edit")';
    $('#save').click(function() {
        $.post(url, $('#userform').serialize(), function(response) {
            if (!response) {
                // display error message the the user was not saved?
            }
        });
    });
    

    which would post back to

    [HttpPost]
    public JsonResult Edit(modeldata model)
    {
        // save the data
        return Json(true); // or return Json(null); if something failed
    }
    

    Note that in the above scripts, the selectors would need to be change to match the actual id attribute generated - i.e. id="name", not id=txtname" etc.

    $('#name').val($(this).data('name'));