How to pass GridView IDs and other controls into j

2019-08-15 22:06发布

问题:

I am learning a lot more about jQuery and Javascript, and I am loving it! The power you have over a webform, control, etc with this language beats client-server methodologies hands down!

One of the most common things people do with scripting languages is control Gridview rows and columns. In my case I am trying to control a Gridview within a cell of another gridview. What I want to do is to checkbox all my checkboxes inside the sub GridView control.

Here is my ASP.net code of the main GridView and the sub Gridview in one of the columns:

        **<asp:GridView ID="gvStudents"** runat="server" DataSourceID="SqlDataSourceStudents" AutoGenerateColumns="False" Width="100%" OnRowDataBound="gvStudents_RowDataBound">
            <HeaderStyle BackColor="#5D7B9D" ForeColor="White" />
            <AlternatingRowStyle BackColor="#EEEEEE" />
            <RowStyle BackColor="White" />
            <Columns>
                <asp:TemplateField HeaderText="Student" >
                    <ItemTemplate>
                        <asp:Label ID="lblName" runat="server" Text='<%# Eval("StudentName") %>' ToolTip='<%# Eval("ProgramName") %>'></asp:Label>
                    </ItemTemplate>
                    <ControlStyle Width="120px" />
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Mobile" >
                    <ItemTemplate>
                        <asp:Label ID="lblMobile" runat="server" Text='<%# Eval("StudentMobilePhone") %>'></asp:Label>
                    </ItemTemplate>
                    <ControlStyle Width="70px" />
                    <ItemStyle HorizontalAlign="Center" />
                </asp:TemplateField>
                <asp:TemplateField>
                    <HeaderTemplate>
                        <asp:CheckBox ID="cbNOKall" runat="server" Text="Next Of Kin" TextAlign="Left"/>
                    </HeaderTemplate>
                    <ItemTemplate>
                        **<asp:GridView ID="gvNOKs"** runat="server" AutoGenerateColumns="False" BorderStyle="None" GridLines="Vertical" ShowHeader="false" ShowFooter="false" BackColor="transparent" >
                            <Columns>
                                <asp:TemplateField HeaderText="Given Name" >
                                    <ItemTemplate>
                                        <asp:Label ID="lblNOKGivenName" runat="server" Text='<%# Eval("NOKname") %>'></asp:Label>
                                    </ItemTemplate>
                                    <ControlStyle Width="150px" />
                                </asp:TemplateField>
                                <asp:TemplateField HeaderText="NoK Type" >
                                    <ItemTemplate>
                                        <asp:Label ID="lblNOKType" runat="server" Text='<%# Eval("NOKType") %>'></asp:Label>
                                    </ItemTemplate>
                                    <ControlStyle Width="100px" />
                                    <ItemStyle HorizontalAlign="Center" />
                                </asp:TemplateField>
                                <asp:TemplateField HeaderText="Mobile" >
                                    <ItemTemplate>
                                        <asp:Label ID="lblNOKMobile" runat="server" Text='<%# Eval("NOKMobile") %>'></asp:Label>
                                    </ItemTemplate>
                                    <ControlStyle Width="100px" />
                                    <ItemStyle HorizontalAlign="Center" />
                                </asp:TemplateField>
                                <asp:TemplateField>
                                    <ItemTemplate>
                                        <asp:CheckBox ID="cbNOKAdd" runat="server" onclick="javascript:SelectAllCheckboxesCol(this);" />
                                    </ItemTemplate>
                                    <ItemStyle HorizontalAlign="Center" />
                                </asp:TemplateField>
                           </Columns>
                        </asp:GridView>
                    </ItemTemplate>
                    <HeaderStyle HorizontalAlign="Center" />
                    <ItemStyle HorizontalAlign="Left" />
                </asp:TemplateField>
                <asp:TemplateField>
                    <HeaderTemplate>
                        <asp:CheckBox id="CheckBoxAll" runat="server" onclick="javascript:SelectAllCheckboxesCol(this);"/>
                    </HeaderTemplate>
                    <ItemTemplate>
                        <asp:CheckBox ID="CheckBoxAdd" runat="server" onclick="javascript:HighlightRow(this);"/>
                    </ItemTemplate>
                    <ItemStyle HorizontalAlign="Center" />
                </asp:TemplateField>
            </Columns>
        </asp:GridView>

Now as you can see, the main GridView has a column of checkboxes and a header checkbox.

I control those checkboxes and the highlights of each row as follows:

    <script type="text/javascript" >
        //jQuery to select all checkboxes on the last column (4th column) of gvStudents
        function SelectAllCheckboxesCol(chk) 
        {
            var cBox = $('#<%=gvStudents.ClientID %> >tbody >tr >td:nth-child(4) > input:checkbox');
            cBox.attr('checked', chk.checked);  //check all the checkboxes
            cBox.click();                       //click them all to fire the Highlightrow() function. This un-ticks the checkboxes!
            cBox.attr('checked', chk.checked);  //re-check them again!
        }

        //jQuery to highlight a row selected
        function HighlightRow(chk) {
            var isChecked = chk.checked;
            var $selectedRow = $("#" + chk.id).parent("td").parent("tr");
            var selectedIndex = $selectedRow[0].rowIndex;
            var sColor = '';

            if(selectedIndex%2 == 0)
                sColor = '#EEEEEE';
            else
                sColor = 'white';

            if(isChecked)
                $selectedRow.css({
                    "background-color" : "Yellow",
                    "color" : "Black"
                });
            else
                $selectedRow.css({
                    "background-color" : sColor,
                    "color" : "Black"
                });
        }
</script>

My questions are:

  • How do I do the same but with the "inner" GridView; and,
  • How do I pass the Gridview IDs into the jQuery scripts and the column number without having to hardcode them in the script to check all the checkboxes?

Thank you for your time.

回答1:

First of all, since you're starting with Javascript / jQuery, I'll give you some suggestions:

  • Always pay attention to the ASP.NET's generated HTML code
  • Since you will be manipulating the Nodes, HTMLElements, etc, it's important to understand them
  • If you're not sure how to find a node, take a time to learn the CSS selectors
  • Study pure/vanilla Javascript before going to jQuery. It's always good to know what you're doing
  • Take a look at the style guides. Functions, for example, should be named camelCased.

I've changed your functions to be generic, independent on the parent GridView.

The fully commented code is below. If you have any questions, please, leave a comment!

function gridViewCheckAll(chk) {
  // parentNode of the chk is the td
  // parentNode of the td is the tr
  // parentNode of the tr is the tbody
  // children of the tbody is the trs
  var cell = chk.parentNode,
      row = cell.parentNode,
      tbody = row.parentNode,
      rows = tbody.children;

  // querySelectorAll to get all the td tags children of tr
  // and indexOf to get what is the index of the chk's td
  // note that I'm using the indexOf Array's method
  // I'm doing that since the property children is not an Array
  var index = [].indexOf.call(row.children, cell);

  // loop through the rows
  for (var i = 1; i < rows.length; i++) {
    // gets the current row, and gets the cell with the same index of the chk's cell
    // then, finds all the checkboxes inside it
    var checkBoxes = rows[i].children[index].querySelectorAll('input[type=checkbox]');

    // loops through the checkboxes and check/highlight them
    for (var j = 0; j < checkBoxes.length; j++) {
      checkBoxes[j].checked = chk.checked;
      highlightRow(checkBoxes[j]);
    }
  }
}

Instead of manually changing the row colors, you could be using CSS classes, and better than that, you could be using the tr:nth-of-type(even) and tr:nth-of-type(odd) for that.

Your HighLightRow function could be rewrited as below:

function highlightRow(chk) {
  var row = chk.parentNode.parentNode;
  if (chk.checked)
    row.classList.add('selected-row');
  else
    row.classList.remove('selected-row');
}

Then, you should have a CSS like this:

table.grid-view > tbody > tr {
  background-color: white;
}

table.grid-view > tbody > tr:nth-of-type(odd) {
  background-color: #EEE;
}

table.grid-view > tbody > tr.selected-row {
  background-color: yellow;
}

And you would need to put a CssClass attribute into your GridView:

<asp:GridView ID="gvStudents" runat="server" CssClass="grid-view" (...)>

And remove the AlternatingRowStyle and RowStyle, since they place a style attribute each row:

<AlternatingRowStyle BackColor="#EEEEEE" />
<RowStyle BackColor="White" />

I've created a plunker for you, so you can play with the code above.