locked
Using datatables, Bootstrap NOT Responsive on GridView for Mobile Phone, Tablet, laptop RRS feed

  • Question

  • User-475949336 posted

    I'm using datatables.net tools for Responsive on GridView for Mobile Phone, Tablet, laptop.

    with the help of Yang Shen, all very well for me.

    Now, I'm facing with little issue, it's responsive.

    The first, zoom in browser to mini size same as mobile screen size for responsive

    1. In list tab, choose 'status' equal 1, then Click '+' sign to extend one row (purpose are mark status of grieview1 )
    - click 'add new' tab, select status is 2
    - click 'list' tab => the status of grieview1 changed and NO RESPONSIVE

    2. Re-enter site http://localhost/CS.aspx in adress bar to load pure page
    - click 'add new' tab
    - choose status to create gridview2
    - click 'list' tab =>>> gridview1 not responstive

    - Change status in list tab to postback then click 'add new' tab ==>gridview2 not responstive

    3.  Remove and add new row

    In 'add new' tab, I  input text, select value for the columns in gridview2, then I REMOVE one row, it's not effect

    I want, after remove row, callback all values that I input, select befored for remain rows.

    This is my  code, try help me soon, thank you advance

    - Main.master
    
    <%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Main.master.cs" Inherits="Quanlynhachothue.Main" %>
    
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
    <meta name="viewport" content="width = device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
        
    <title></title>
    
    <link rel="stylesheet" href='http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css' media="screen" />
    
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
    
    
    
    <script type="text/javascript" src='http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.0.3/js/bootstrap.min.js'></script>
    
    
      <link rel="stylesheet" type="text/css" href="./css-js-Gridview/datatables.min-1.10.20.css" />      
    <script type="text/javascript" src="./css-js-Gridview/datatables.min-1.10.20.js"></script>
    <style type="text/css"> @media (max-width: 992px) { .navbar-header { float: none; } .navbar-left,.navbar-right { float: none !important; } .navbar-toggle { display: block; } .navbar-collapse { border-top: 1px solid transparent; box-shadow: inset 0 1px 0 rgba(255,255,255,0.1); } .navbar-fixed-top { top: 0; border-width: 0 0 1px; } .navbar-collapse.collapse { display: none!important; } .navbar-nav { float: none!important; margin-top: 7.5px; } .navbar-nav>li { float: none; } .navbar-nav>li>a { padding-top: 10px; padding-bottom: 10px; } .collapse.in{ display:block !important; } } .dropdown-submenu { ; } .dropdown-submenu > .dropdown-menu { top: 0; left: 100%; margin-top: -6px; margin-left: -1px; -webkit-border-radius: 0 6px 6px 6px; -moz-border-radius: 0 6px 6px 6px; border-radius: 0 6px 6px 6px; } .dropdown-submenu > a:after { display: block; content: " "; float: right; width: 0; height: 0; border-color: transparent; border-style: solid; border-width: 5px 0 5px 5px; border-left-color: #cccccc; margin-top: 5px; margin-right: -10px; } .dropdown-submenu:hover > a:after { border-left-color: #555; } .dropdown-submenu.pull-left { float: none; } .dropdown-submenu.pull-left > .dropdown-menu { left: -100%; margin-left: 10px; -webkit-border-radius: 6px 0 6px 6px; -moz-border-radius: 6px 0 6px 6px; border-radius: 6px 0 6px 6px; } </style> <asp:ContentPlaceHolder ID="head" runat="server"> </asp:ContentPlaceHolder> </head> <body> <form id="main" runat="server"> <div class="navbar navbar-default" style="font-family:Arial; background-color: #0066CC"> <div class="container-fluid" style="font-family:Arial"> <div class="navbar-header" style="font-family:Arial"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span> </button> <a class="navbar-brand" href="./">ASP</a> </div> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1" style="font-family:Arial;background-color: #1A8CFF" > <asp:Menu ID="Menu1" runat="server" Orientation="Horizontal" RenderingMode="List" IncludeStyleBlock="false" StaticMenuStyle-CssClass="nav navbar-nav" DynamicMenuStyle-CssClass="dropdown-menu"> </asp:Menu> </div> </div> </div> <script type="text/javascript"> Sys.WebForms.Menu._elementObjectMapper.getMappedObject = function () { return false; }; $(function () { $(".navbar-nav li, .navbar-nav a, .navbar-nav ul").removeAttr('style'); $(".dropdown-menu").closest("li").removeClass().addClass("dropdown-toggle"); $(".dropdown-toggle").find("a[href='javascript:;']").attr("data-toggle", "dropdown"); $(".dropdown-toggle").find("a[href='javascript:;'].level1").append("<span class='caret'></span>"); $(".dropdown-toggle").find("a[href='javascript:;']:not(.level1)").closest('li').addClass('dropdown-submenu'); $("a.selected").closest("li").addClass("active"); $("a.selected").closest(".dropdown-toggle").addClass("active"); $('ul.dropdown-menu [data-toggle=dropdown]').on('click', function (event) { event.preventDefault(); event.stopPropagation(); $(this).parent().siblings().removeClass('open'); $(this).parent().toggleClass('open'); }); }); </script> <hr /> <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server"> </asp:ContentPlaceHolder> </form> </body> </html> - Main.master.cs using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace Quanlynhachothue { public partial class Main : System.Web.UI.MasterPage { protected void Page_Load(object sender, EventArgs e) { if (!this.IsPostBack) { DataTable dt = this.GetData(0); PopulateMenu(dt, 0, null); } } private DataTable GetData(int parentMenuId) { DataTable dt = new DataTable(); dt.Columns.AddRange(new DataColumn[4] { new DataColumn("ParentMenuId"), new DataColumn("MenuId"), new DataColumn("Title"), new DataColumn("Url") }); dt.Rows.Add(0, 1, "Home", "~/CS.aspx"); dt.Rows.Add(0, 2, "Services", "javascript:;"); dt.Rows.Add(0, 3, "About", "javascript:;"); dt.Rows.Add(0, 4, "Contact ", "~/frmtabcontrolHoadonDichvu.aspx"); dt.Rows.Add(2, 5, "Consulting", "~/Consulting.aspx"); dt.Rows.Add(2, 6, "Outsourcing ", "~/Outsourcing.aspx"); dt.Rows.Add(3, 7, "About1", "javascript:;"); dt.Rows.Add(3, 8, "About2", "~/About2.aspx"); dt.Rows.Add(7, 9, "About11", "~/About11.aspx"); dt.Rows.Add(7, 10, "About12", "~/About12.aspx"); DataTable dtFinal = dt.Clone(); DataRow[] dr = dt.Select("ParentMenuId=" + parentMenuId); if (dr.Length > 0) { dtFinal = dr.CopyToDataTable(); } return dtFinal; } private void PopulateMenu(DataTable dt, int parentMenuId, MenuItem parentMenuItem) { string currentPage = Path.GetFileName(Request.Url.AbsolutePath); foreach (DataRow row in dt.Rows) { MenuItem menuItem = new MenuItem { Value = row["MenuId"].ToString(), Text = row["Title"].ToString(), NavigateUrl = row["Url"].ToString(), Selected = row["Url"].ToString().EndsWith(currentPage, StringComparison.CurrentCultureIgnoreCase) }; if (parentMenuId == 0) { Menu1.Items.Add(menuItem); DataTable dtChild = this.GetData(int.Parse(menuItem.Value)); PopulateMenu(dtChild, int.Parse(menuItem.Value), menuItem); } else { parentMenuItem.ChildItems.Add(menuItem); if (parentMenuId > 0) { DataTable dtChild = this.GetData(int.Parse(menuItem.Value)); PopulateMenu(dtChild, int.Parse(menuItem.Value), menuItem); } } } } } }
    - CS.aspx.cs

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;

    namespace Quanlynhachothue
    {
    public partial class CS : System.Web.UI.Page
    {
    protected void Page_Load(object sender, EventArgs e)
    {
    if (!this.IsPostBack)
    {
    DataTable dt = new DataTable();
    dt.Columns.AddRange(new DataColumn[5] { new DataColumn("Id"), new DataColumn("Name"), new DataColumn("Country"), new DataColumn("Salary"), new DataColumn("Job") });
    dt.Rows.Add(1, "John Hammond", "United States", 70000,"IT");
    dt.Rows.Add(2, "Mudassar Khan", "India", 40000, "Bank");
    dt.Rows.Add(3, "Suzanne Mathews", "France", 30000,"Sport");
    dt.Rows.Add(4, "Robert Schidner", "Russia", 50000,"Finace");

    GridView1.DataSource = dt;
    GridView1.DataBind();
    Mobile_List();

    ButtonAdd.Visible = false;
    ButtonSaveAll.Visible = false;
    }
    else
    Mobile_List();


    }

    protected void Create_GridView2()
    {
    DataTable dt1 = new DataTable();
    DataRow dr = null;

    dt1.Columns.AddRange(new DataColumn[6]
    {
    new DataColumn("MyId"),
    new DataColumn("MyName"),
    new DataColumn("CountryCode"),
    new DataColumn("MyCountry"),
    new DataColumn("MySalary"),
    new DataColumn("Job")

    });


    for (int i = 1; i < 5; i++)
    {
    dr = dt1.NewRow();
    dr["MyId"] = i;
    dr["MyName"] = string.Empty;
    dr["CountryCode"] = i;
    dr["MySalary"] = string.Empty;

    dt1.Rows.Add(dr);
    }

    //Store the DataTable in ViewState for future reference
    ViewState["CurrentTable"] = dt1;

    //Bind the Gridview
    GridView2.DataSource = dt1;
    GridView2.DataBind();

    Mobile_addnew();

    DropDownList ddl1 = null;
    DropDownList ddl2 = null;

    DataTable dtCurrentTable = (DataTable)ViewState["CurrentTable"];

    //After binding the gridview, we can then extract and fill the DropDownList with Data
    for (int j = 0; j < dtCurrentTable.Rows.Count; j++)
    {
    ddl1 = (DropDownList)GridView2.Rows[j].Cells[3].FindControl("txtCountry");
    ddl2 = (DropDownList)GridView2.Rows[j].Cells[5].FindControl("txtJob");

    Label txt_CountryCode = (Label)GridView2.Rows[j].Cells[2].FindControl("txtCountryCode");
    ddl1.SelectedValue = txt_CountryCode.Text;

    DropDownList_Country(ddl1);
    DropDownList_Job(ddl2);

    }


    }

    public static void DropDownList_Country(DropDownList ddl)
    {
    System.Collections.ArrayList arr = new System.Collections.ArrayList();

    arr.Add(new ListItem("United States", "1"));
    arr.Add(new ListItem("India", "2"));
    arr.Add(new ListItem("France", "3"));
    arr.Add(new ListItem("Russia", "4"));

    foreach (ListItem item in arr)
    {
    ddl.Items.Add(item);
    }
    }

    public static void DropDownList_Job(DropDownList ddl)
    {
    System.Collections.ArrayList arr = new System.Collections.ArrayList();

    arr.Add(new ListItem("IT", "1"));
    arr.Add(new ListItem("Cutural", "2"));
    arr.Add(new ListItem("Sport", "3"));
    arr.Add(new ListItem("finance", "4"));
    arr.Add(new ListItem("Bank", "5"));

    foreach (ListItem item in arr)
    {
    ddl.Items.Add(item);
    }
    }

    private void AddNewRowToGrid()
    {

    if (ViewState["CurrentTable"] != null)
    {

    DataTable dtCurrentTable = (DataTable)ViewState["CurrentTable"];
    DataRow drCurrentRow = null;

    if (dtCurrentTable.Rows.Count > 0)
    {
    drCurrentRow = dtCurrentTable.NewRow();
    drCurrentRow["MyId"] = dtCurrentTable.Rows.Count + 1;

    //add new row to DataTable
    dtCurrentTable.Rows.Add(drCurrentRow);

    for (int i = 0; i < dtCurrentTable.Rows.Count - 1; i++)
    {

    //extract the TextBox values

    TextBox txt_Name = (TextBox)GridView2.Rows[i].Cells[1].FindControl("txtName");
    Label txt_CountryCode = (Label)GridView2.Rows[i].Cells[2].FindControl("txtCountryCode");

    TextBox txt_Salary = (TextBox)GridView2.Rows[i].Cells[4].FindControl("txtSalary");


    dtCurrentTable.Rows[i]["MyName"] = txt_Name.Text;
    dtCurrentTable.Rows[i]["CountryCode"] = txt_CountryCode.Text;
    dtCurrentTable.Rows[i]["MySalary"] = txt_Salary.Text;

    //extract the DropDownList Selected Items

    DropDownList ddl1 = (DropDownList)GridView2.Rows[i].Cells[3].FindControl("txtCountry");
    DropDownList ddl2 = (DropDownList)GridView2.Rows[i].Cells[5].FindControl("txtJob");

    // Update the DataRow with the DDL Selected Items

    dtCurrentTable.Rows[i]["MyCountry"] = ddl1.SelectedItem.Text;
    dtCurrentTable.Rows[i]["Job"] = ddl2.SelectedItem.Text;
    }

    //Store the current data to ViewState for future reference
    ViewState["CurrentTable"] = dtCurrentTable;


    //Rebind the Grid with the current data to reflect changes
    GridView2.DataSource = dtCurrentTable;
    GridView2.DataBind();
    Mobile_addnew();
    }
    }
    else
    {
    Response.Write("ViewState is null");

    }
    //Set Previous Data on Postbacks
    SetPreviousData();
    }
    public void Mobile_addnew()
    {
    /*
    if (GridView2.Rows.Count > 0)
    {
    GridView2.HeaderRow.Cells[0].Attributes["data-class"] = "expand";
    //Attribute to hide column in Phone.
    GridView2.HeaderRow.Cells[1].Attributes["data-hide"] = "phone";
    GridView2.HeaderRow.Cells[4].Attributes["data-hide"] = "phone";
    GridView2.HeaderRow.Cells[5].Attributes["data-hide"] = "phone";

    //Adds THEAD and TBODY to GridView.
    GridView2.HeaderRow.TableSection = TableRowSection.TableHeader;
    }
    */
    GridView2.HeaderRow.TableSection = TableRowSection.TableHeader;

    }

    public void Mobile_List()
    {
    /*
    if (GridView1.Rows.Count > 0)
    {
    //Attribute to show the Plus Minus Button.
    GridView1.HeaderRow.Cells[0].Attributes["data-class"] = "expand";
    //Attribute to hide column in Phone.
    GridView1.HeaderRow.Cells[2].Attributes["data-hide"] = "phone";
    GridView1.HeaderRow.Cells[3].Attributes["data-hide"] = "phone";

    //Adds THEAD and TBODY to GridView.
    GridView1.HeaderRow.TableSection = TableRowSection.TableHeader;
    }
    */
    GridView1.HeaderRow.TableSection = TableRowSection.TableHeader;

    }
    protected void DropDownList_Status_selectedIndexChanged(object sender, EventArgs e)
    {
    if (DropDownList_Status.SelectedItem.Text != "All")
    {
    Create_GridView2();
    ButtonAdd.Visible = true;
    ButtonSaveAll.Visible = true;
    }
    else
    {
    GridView2.DataSource = null;
    GridView2.DataBind();

    ButtonAdd.Visible = false;
    ButtonSaveAll.Visible = false;
    }

    }

    protected void ButtonSaveAll_Click(object sender, EventArgs e)
    {

    }

    protected void bttRemoveRow_Click(object sender, EventArgs e)
    {
    Button btt = (Button)sender;
    GridViewRow gvRow = (GridViewRow)btt.NamingContainer;
    int rowID = gvRow.RowIndex;
    if (ViewState["CurrentTable"] != null)
    {

    DataTable dt = (DataTable)ViewState["CurrentTable"];
    if (dt.Rows.Count > 1)
    {
    if (gvRow.RowIndex <= dt.Rows.Count - 1)
    {
    //Remove the Selected Row data and reset row number
    dt.Rows.Remove(dt.Rows[rowID]);
    ResetRowID(dt);
    }
    }

    //Store the current data in ViewState for future reference
    ViewState["CurrentTable"] = dt;

    //Re bind the GridView for the updated data
    GridView2.DataSource = dt;
    GridView2.DataBind();
    Mobile_addnew();
    }

    //Set Previous Data on Postbacks
    // Yang Shen comment SetPreviousData();

    // Yang Shen begin
    DropDownList ddl1 = null;
    DropDownList ddl2 = null;
    DataTable dtCurrentTable = (DataTable)ViewState["CurrentTable"];
    //After binding the gridview, we can then extract and fill the DropDownList with Data
    for (int j = 0; j < dtCurrentTable.Rows.Count; j++)
    {
    ddl1 = (DropDownList)GridView2.Rows[j].Cells[3].FindControl("txtCountry");
    ddl2 = (DropDownList)GridView2.Rows[j].Cells[5].FindControl("txtJob");

    Label txt_CountryCode = (Label)GridView2.Rows[j].Cells[2].FindControl("txtCountryCode");
    ddl1.SelectedValue = txt_CountryCode.Text;

    DropDownList_Country(ddl1);
    DropDownList_Job(ddl2);

    }
    // Yang Shen end
    }

    protected void ButtonAdd_Click(object sender, EventArgs e)
    {
    AddNewRowToGrid();
    }

    private void ResetRowID(DataTable dt)
    {
    int rowNumber = 1;
    if (dt.Rows.Count > 0)
    {
    foreach (DataRow row in dt.Rows)
    {
    row[0] = rowNumber;
    rowNumber++;
    }
    }
    }
    private void SetPreviousData()
    {

    int rowIndex = 0;
    if (ViewState["CurrentTable"] != null)
    {

    DataTable dt = (DataTable)ViewState["CurrentTable"];
    if (dt.Rows.Count > 0)
    {

    for (int i = 0; i < dt.Rows.Count; i++)
    {

    Label txt_Id = (Label)GridView2.Rows[i].Cells[0].FindControl("txtId");
    TextBox txt_Name = (TextBox)GridView2.Rows[i].Cells[1].FindControl("txtName");
    Label txt_CountryCode = (Label)GridView2.Rows[i].Cells[2].FindControl("txtCountryCode");
    TextBox txt_Salary = (TextBox)GridView2.Rows[i].Cells[4].FindControl("txtSalary");

    DropDownList ddl1 = (DropDownList)GridView2.Rows[rowIndex].Cells[3].FindControl("txtCountry");
    DropDownList ddl2 = (DropDownList)GridView2.Rows[rowIndex].Cells[5].FindControl("txtJob");

    //Fill the DropDownList with Data
    DropDownList_Country(ddl1);
    DropDownList_Job(ddl2);

    if (i < dt.Rows.Count - 1)
    {
    txt_Id.Text = dt.Rows[i]["MyId"].ToString();
    txt_Name.Text = dt.Rows[i]["MyName"].ToString();
    txt_CountryCode.Text = dt.Rows[i]["CountryCode"].ToString();
    txt_Salary.Text = dt.Rows[i]["MySalary"].ToString();


    //Set the Previous Selected Items on Each DropDownList on Postbacks
    ddl1.ClearSelection();
    ddl1.Items.FindByText(dt.Rows[i]["MyCountry"].ToString()).Selected = true;

    ddl2.ClearSelection();
    ddl2.Items.FindByText(dt.Rows[i]["Job"].ToString()).Selected = true;
    }

    rowIndex++;
    }
    }
    }
    }
    }
    }

     
     
    <%@ Page Title="" Language="C#" MasterPageFile="~/Main.master" UnobtrusiveValidationMode="None" EnableEventValidation="false"  AutoEventWireup="true" CodeBehind="CS.aspx.cs" Inherits="Quanlynhachothue.CS" %>
    <%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>
    
    <asp:Content id="Content1" ContentPlaceHolderID="head" Runat="Server">     
         
    
    </asp:Content> 
    
    <asp:Content id="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">          
    
        <asp:UpdatePanel id="UpdatePanel1" runat="server"> 
        <ContentTemplate>
       
        <div class="tab-content" style="width: auto; border:none; font-family:Arial; font-size:larger; color:#1443AB; font-weight:bold; text-align:center; padding: 1px; margin: 1px">
         GRIDVIEW
        </div> 
                           <div class="panel panel-default" style="width: auto; padding: 6px; margin: 6px">
    
                            <div id="dvTab">
                                
                                <ul class="nav nav-tabs" role="tablist"  style="font-weight: bold">
                                    <li runat="server" id="idListtab" class="active"><a href="#Listtab" style="outline:none" aria-controls="Listtab" role="tab"  data-toggle="tab">LIST</a></li>
                                    <li runat="server" id="idAddnewtab"><a href="#Addnewtab" style="outline:none" aria-controls="Addnewtab" role="tab" data-toggle="tab">ADD NEW</a></li>
                                    <li runat="server" id="idEdittab"><a href="#Edittab" style="outline:none" aria-controls="Edittab" role="tab" data-toggle="tab">EDIT</a></li>
                                    <li runat="server" id="idViewtab"><a href="#Viewtab" style="outline:none" aria-controls="Viewtab" role="tab" data-toggle="tab">VIEW</a></li>
                                                                  
                                </ul>
    
      <div class="tab-content" style="padding-top: 5px">
                                    
      <!-- Begin List -->  
       <div role="tabpanel"  class="tab-pane active" id="Listtab">                    
                                       
        <div> 
    
        <asp:ScriptManager id="toolScriptManageer1" runat="server" EnablePartialRendering="false">
        </asp:ScriptManager> 
     
    	<label for="tungay">From &nbsp;&nbsp;&nbsp;       
        <asp:TextBox id="txtTungay" width="128px" Height ="30px" runat="server" MaxLength="10"  AutoPostBack="true"   ></asp:TextBox>            
                <ajaxToolkit:CalendarExtender id="Calendarfromdate" popupbuttonid="imgPopup" runat="server" targetcontrolid="txtTungay" format="dd/MM/yyyy" />
    	</label> 
       
            
        <label for="denngay">To &nbsp;
             
        <asp:TextBox id="txtDenngay" width="128px" Height ="30px"   AutoPostBack="true" runat="server" MaxLength="10" ></asp:TextBox>  
            <ajaxToolkit:CalendarExtender id="Calendartodate" popupbuttonid="imgPopup" runat="server" targetcontrolid="txtDenngay" format="dd/MM/yyyy" />	
    
        </label> 
    		 
    
       <label for="trangthai">Status&nbsp;
        <asp:DropDownList id="txtTrangthai" width="128px" Height ="30px"  AutoPostBack="true" runat="server" >    
        <asp:ListItem Text="All" Value="All"></asp:ListItem>
        <asp:ListItem Text="1" Value="1"></asp:ListItem>
        <asp:ListItem Text="2" Value="2"></asp:ListItem>
        </asp:DropDownList>
        </label>	
        
     </div>
     <br/>
     
        <asp:GridView id="GridView1"  CssClass="dt-responsive" class="display" Width="100%"  runat="server" AutoGenerateColumns="false" HeaderStyle-BackColor="#BED7F3" HeaderStyle-Height="30px" HeaderStyle-BorderStyle="None" HeaderStyle-ForeColor="#144383"  Font-Names="Arial" HeaderStyle-Font-Size="13px" >
        
        <Columns>
                <asp:BoundField DataField="Id" HeaderText="Customer Id" />
                <asp:BoundField DataField="Name" HeaderText="Customer Name" />
                <asp:BoundField DataField="Country" HeaderText="Country" />
            
              <asp:TemplateField HeaderText="Salary" >
                        <ItemTemplate>
                            <asp:textbox ID="txtSalary" Text='<%# Eval("Salary") %>'   Width="80px"  runat="server"></asp:textbox>
                        </ItemTemplate>
               </asp:TemplateField>
               
             <asp:BoundField DataField="Job" HeaderText="Job" />         
            
        </Columns>                       
        </asp:GridView> 
    
        <input type="hidden" runat="server" id="hidMaHDDV" />                       
                                       
        </div>                                                              
        <!-- End List -->
    
    
         <!-- Begin Addnew -->
          <div role="tabpanel" class="tab-pane" id="Addnewtab">
                
          <div> 
           
          <label for="thangnam">Month &nbsp;&nbsp;&nbsp;       
                          <asp:TextBox id="txtThangNam_addnew"  width="128px"   Height ="30px" runat="server"  MaxLength="7" ></asp:TextBox>            
    
                          <ajaxToolkit:CalendarExtender id="calendar1" ClientIDMode="Static" runat="server" TargetControlID="txtThangNam_addnew" Format="MM/yyyy" 
                          DefaultView="Months" OnClientShown="onCalendarShown"
                          OnClientHidden="onCalendarHidden" PopupButtonID="imgStart" />                        
           </label> 
    
        <label for="trangthai">Status&nbsp;
        <asp:DropDownList id="DropDownList_Status"  OnSelectedIndexChanged="DropDownList_Status_selectedIndexChanged"   AutoPostBack="true" runat="server" >    
        <asp:ListItem Text="All" Value="All"></asp:ListItem>
        <asp:ListItem Text="1" Value="1"></asp:ListItem>
        <asp:ListItem Text="2" Value="2"></asp:ListItem>
        </asp:DropDownList>
        </label>	
                 
        </div>
        
          
          <asp:Gridview id="GridView2" CssClass="dt-responsive" class="display" Width="100%"   runat="server" AutoGenerateColumns="false" HeaderStyle-BackColor="#BED7F3" HeaderStyle-Height="30px" HeaderStyle-BorderStyle="None" HeaderStyle-ForeColor="#144383"  Font-Names="Arial" HeaderStyle-Font-Size="13px">
                      
                <Columns>                
                
                    <asp:TemplateField HeaderText="Id" >
                        <ItemTemplate>
                            <asp:Label ID="txtId" Width="80px"  Text='<%# Eval("MyId") %>'  runat="server"></asp:Label>
                        </ItemTemplate>
                    </asp:TemplateField>
                                    
                    <asp:TemplateField HeaderText="Customer Name" >
                        <ItemTemplate>
                            <asp:textbox ID="txtName" Width="80px"  Text='<%# Eval("MyName") %>'  runat="server"></asp:textbox>
                        </ItemTemplate>
                    </asp:TemplateField>
                                    
                     <asp:TemplateField HeaderText="CountryCode" Visible="false">
                        <ItemTemplate>
                            <asp:Label ID="txtCountryCode" Text='<%# Eval("CountryCode") %>'  runat="server" Visible="false"></asp:Label>
                        </ItemTemplate>
                    </asp:TemplateField>
    
    
                     <asp:TemplateField HeaderText="Country" >
                        <ItemTemplate>
                             <asp:DropDownList ID="txtCountry"  Width="100px" runat="server" AppendDataBoundItems="true">
                            </asp:DropDownList>
                        </ItemTemplate>
                    </asp:TemplateField>
    
                    <asp:TemplateField HeaderText="Salary" >
                        <ItemTemplate>
                            <asp:textbox ID="txtSalary"  Width="80px"  runat="server"></asp:textbox>
                        </ItemTemplate>
                    </asp:TemplateField>
    
                    <asp:TemplateField HeaderText="Job" >
                        <ItemTemplate>
                             <asp:DropDownList ID="txtJob"   runat="server" AppendDataBoundItems="true">
                            </asp:DropDownList>
                        </ItemTemplate>
                    </asp:TemplateField>
    
    
                    <asp:TemplateField HeaderText="Remove" HeaderStyle-Width="50px" >
                        <ItemTemplate>
                            <asp:Button ID="bttRemoveRow" Width="100px" Text="Remove row" runat="server" onclick="bttRemoveRow_Click" Class="btn-primary"></asp:Button>
                        </ItemTemplate>
                    </asp:TemplateField>
                                                            
                </Columns>
            </asp:Gridview>        
         
         <div align="right" >
         <asp:Button ID="ButtonAdd" runat="server"  Text="Add row"   onclick="ButtonAdd_Click" Class="btn-primary" />
         </div>
                     
              
         <div align="Left" >
         <asp:Button  ID="ButtonSaveAll" runat="server"  Text="Save all row"   onclick="ButtonSaveAll_Click" Class="btn-primary" />
         </div>
              
                     
        </div>
         <!-- End Addnew -->
    
          <!-- Begin Edit -->
            <div role="tabpanel" class="tab-pane" id="Edittab">
                 Edit         
            </div>
          <!-- End Edit -->
    
    
           <!-- Begin View -->
             <div role="tabpanel" class="tab-pane" id="Viewtab">
                View 
             </div>
            <!-- End View -->
                                    
            </div>
            </div>
            </div>
    
        <asp:HiddenField ID="HiddenTab" runat="server" />
    
        </ContentTemplate>
        </asp:UpdatePanel>
    
         <!-- Panel  End-->              
         
        <script type="text/javascript">
        
            function RememberValue() {
             // var table = $('#example').DataTable({           
               var table = $('#<%=GridView2.ClientID%>').DataTable({                
                    'columnDefs': [
                       {
                           //"defaultContent": "-",
                           'targets': [1,2,3,4],
                           'render': function (data, type, row, meta) {
                               if (type === 'display') {
                                   var api = new $.fn.dataTable.Api(meta.settings);
    
                                   var $el = $('input, select, textarea', api.cell({ row: meta.row, column: meta.col }).node());
    
                                   var $html = $(data).wrap('<div/>').parent();
    
                                   if ($el.prop('tagName') === 'INPUT') {
                                       $('input', $html).attr('value', $el.val());
                                       if ($el.prop('checked')) {
                                           $('input', $html).attr('checked', 'checked');
                                       }
                                   } else if ($el.prop('tagName') === 'TEXTAREA') {
                                       $('textarea', $html).html($el.val());
    
                                   } else if ($el.prop('tagName') === 'SELECT') {
                                       $('option:selected', $html).removeAttr('selected');
                                       $('option', $html).filter(function () {
                                           return ($(this).attr('value') === $el.val());
                                       }).attr('selected', 'selected');
                                   }
    
                                   data = $html.html();
                               }
    
                               return data;
                           }
                       }
                    ],
                    'responsive': true
                });
    
                // Update original input/select on change in child row
                $('#<%=GridView2.ClientID%> tbody').on('keyup change', '.child input, .child select, .child textarea', function (e) {
                
                    var $el = $(this);
                    var rowIdx = $el.closest('ul').data('dtr-index');
                    var colIdx = $el.closest('li').data('dtr-index');
                    var cell = table.cell({ row: rowIdx, column: colIdx }).node();
                    $('input, select, textarea', cell).val($el.val());
                    if ($el.is(':checked')) {
                        $('input', cell).prop('checked', true);
                    } else {
                        $('input', cell).removeProp('checked');
                    }
                });
            };
    
    
            $(function ()
            {
                SetTabs();
             //   $('#<%=GridView2.ClientID%>').DataTable({ "paging": false, "ordering": false, "searching": false });
              RememberValue();
    
        });
    
    
        var prm = Sys.WebForms.PageRequestManager.getInstance();
        if (prm != null)
        {
            prm.add_endRequest(function (sender, e) {
                if (sender._postBackSettings.panelsToUpdate != null) {
                    SetTabs();
               
                   // $('#<%=GridView2.ClientID%>').DataTable({ "paging": false, "ordering": false, "searching": false });                            
                    RememberValue();
                }
            });
        };
        function SetTabs() {
            var tabName = $("[id*=HiddenTab]").val() != "" ? $("[id*=HiddenTab]").val() : "Listtab";
            $('#dvTab a[href="#' + tabName + '"]').tab('show');
            $("#dvTab a").click(function () {
            $("[id*=HiddenTab]").val($(this).attr("href").replace("#", ""));
            });
        };
       
    </script>      
        
         <script type="text/javascript">
                               
             function pageLoad() {
                $('#<%=GridView1.ClientID%>').DataTable({ "paging": false, "ordering": false, "searching": false });
             }
        </script>      
        
        
      <script type="text/javascript">
         function onCalendarHidden() {  // Call on Addnew 
            var cal = $find("calendar1");
    
            if (cal._monthsBody) {
                for (var i = 0; i < cal._monthsBody.rows.length; i++) {
                    var row = cal._monthsBody.rows[i];
                    for (var j = 0; j < row.cells.length; j++) {
                        Sys.UI.DomEvent.removeHandler(row.cells[j].firstChild, "click", call);
                    }
                }
            }
         }
             
        function onCalendarShown() {
    
            var cal = $find("calendar1");
    
            cal._switchMode("months", true);
    
            if (cal._monthsBody) {
                for (var i = 0; i < cal._monthsBody.rows.length; i++) {
                    var row = cal._monthsBody.rows[i];
                    for (var j = 0; j < row.cells.length; j++) {
                        Sys.UI.DomEvent.addHandler(row.cells[j].firstChild, "click", call);
                    }
                }
            }
        }
    
        function call(eventElement) {
            var target = eventElement.target;
            switch (target.mode) {
                case "month":
                    var cal = $find("calendar1");
                    cal._visibleDate = target.date;
                    cal.set_selectedDate(target.date);
                    //cal._switchMonth(target.date);
                    cal._blur.post(true);
                    cal.raiseDateSelectionChanged();
                    break;
            }
        }
      </script>       
        
        
    </asp:Content>

    Friday, April 10, 2020 5:39 AM

Answers

  • User-1330468790 posted

    Hi test0101,

     

    test0101

    1- Add this to CS.aspx:

    <asp:TemplateField HeaderText="Remove" HeaderStyle-Width="50px" >
    <ItemTemplate>
    <asp:Button ID="bttRemoveRow" Width="100px" Text="Remove row" runat="server" onclick="bttRemoveRow_Click" onClientclick="Collapse_all_rows(); return true;" Class="btn-primary"></asp:Button>
    </ItemTemplate>
    </asp:TemplateField>

    <asp:Button ID="ButtonAdd" runat="server" Text="Add row" onclick="ButtonAdd_Click" onClientclick="Collapse_all_rows(); return true;" Class="btn-primary" />

    function Collapse_all_rows()
    {
    var table = $('#<%=GridView2.ClientID%>').DataTable();
    table.rows('.parent').nodes().to$().find('td:first-child').trigger('click');
    // table.rows('.parent').nodes().to$().find('td:first-child').trigger('touchstart');  // I try this, it same as 'click' is no action when 'remove' button is hidden
    }

    I tried these codes and I clicked the add_new button which perform normally from my side.

    You can as below. 

    Could you please tell me which browser you are using to test the code? It may be helpful to reproduce the problem.

     

    test0101

    2- open brower, resize in order to bttRemoveRow button hiddend on brower then click '+' sign to extend one row, input salary,  click '+' sgn on another row, click 'remove' this row. (with me, when click 'remove' it no action). 

    I tested 'Add row' button action nomal on PC, laptop, Mobile. Only 'remove row' no action when it hidden on brower.

    BTW, I agree with you, when input salary no need typing ',' sign, it automatic add by javascript, as my:

    <asp:textbox ID="txtSalary1" onkeyup="isNumberKey(this);" Text='<%# Eval("MySalary1") %>' Width="80px" runat="server"></asp:textbox>

    function isNumberKey(i)
    {
    if (i.value.length > 0){
    i.value = i.value.replace(/[^\d]+/g, ''); // Only number
    i.value = i.value.replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,"); // group for currency
    } }

    Reason why "remove button" not working:

    When you trigger the collapse function, the remove button is also removed.

    About the isNumberKey():

    If you insist on using this function to format the currency text in the text box, you will still need to process the string in the future when you have to use database. You will find that dealing with a number is much easier than dealing with a format string.

    Again, there is no need to format the user input. Instead, you should verify it to check if it is a number.

     

    Best regards,

    Sean

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, April 16, 2020 9:51 AM

All replies

  • User-1330468790 posted

    Hi test0101,

     

    You should start from a very simple code rather than putting all of the code together. There are lots of improvement to do with your code.

    Please always bear in mind that "don’t repeat yourself" while I can see some duplicated parts so that it becomes very difficult to read and maintain your code.

      

    3.  Remove and add new row

    In 'add new' tab, I  input text, select value for the columns in gridview2, then I REMOVE one row, it's not effect

    I want, after remove row, callback all values that I input, select befored for remain rows.

    As Shen Yang commented in the code, you should keep the data in the ViewState["CurrentTable"] variable, which you have done for the adding row operation but not for the deleting operation. Therefore, you could not retain the value in the "GridView2" control.

    I modified the previous method "bttRemoveRow_Click" and add one method called "UpdateCurrentDataTable" which is used to update the gridview data into ViewState["CurrentTable"]. 

    protected void bttRemoveRow_Click(object sender, EventArgs e)
            {
                UpdateCurrentDataTable(GridView2);
                Button btt = (Button)sender;
                GridViewRow gvRow = (GridViewRow)btt.NamingContainer;
                int rowID = gvRow.RowIndex;
                if (ViewState["CurrentTable"] != null)
                {
    
                    DataTable dt = (DataTable)ViewState["CurrentTable"];
                    if (dt.Rows.Count > 1)
                    {
                        if (gvRow.RowIndex <= dt.Rows.Count - 1)
                        {
                            //Remove the Selected Row data and reset row number
                            dt.Rows.Remove(dt.Rows[rowID]);
                            ResetRowID(dt);
                        }
                    }
    
                    //Store the current data in ViewState for future reference
                    ViewState["CurrentTable"] = dt;
    
                    //Re bind the GridView for the updated data except dropdown lists
                    GridView2.DataSource = dt;
                    GridView2.DataBind();
                    Mobile_addnew();
    
    
    
                    //After binding the gridview, we can then extract and fill the DropDownList with Data
                    for (int j = 0; j < dt.Rows.Count; j++)
                    {
                        DropDownList ddl1 = (DropDownList)GridView2.Rows[j].FindControl("txtCountry");
                        DropDownList ddl2 = (DropDownList)GridView2.Rows[j].FindControl("txtJob");
                        TextBox txt_Salary = (TextBox)GridView2.Rows[j].FindControl("txtSalary");
    
                        txt_Salary.Text = dt.Rows[j]["MySalary"].ToString();
    
                        DropDownList_Country(ddl1);
                        DropDownList_Job(ddl2);
    
    
                        Label txt_CountryCode = (Label)GridView2.Rows[j].Cells[2].FindControl("txtCountryCode");
                        ddl1.SelectedValue = txt_CountryCode.Text;
    
                        ddl1.ClearSelection();
                        ddl1.Items.FindByText(dt.Rows[j]["MyCountry"].ToString()).Selected = true;
    
                        ddl2.ClearSelection();
                        ddl2.Items.FindByText(dt.Rows[j]["Job"].ToString()).Selected = true;
    
                    }
                }
                
            }
    
           
    
            private void UpdateCurrentDataTable(GridView gv)
            {
                int rowIndex = 0;
                if (ViewState["CurrentTable"] != null)
                {
                    DataTable dt = (DataTable)ViewState["CurrentTable"];
                    foreach (GridViewRow row in gv.Rows)
                    {
                        Label lbl_Id = (Label)row.FindControl("txtId");
                        TextBox tb_Name = (TextBox)row.FindControl("txtName");
                        DropDownList dpl_Country = (DropDownList)row.FindControl("txtCountry");
                        TextBox tb_Salary = (TextBox)row.FindControl("txtSalary");
                        DropDownList dpl_Job = (DropDownList)row.FindControl("txtJob");
    
                        int id = Convert.ToInt32(lbl_Id.Text);
                        string name = tb_Name.Text;
                        int countryCode = Convert.ToInt32(dpl_Country.SelectedValue);
                        string country = dpl_Country.SelectedItem.Text;
                        string salary = tb_Salary.Text;
                        string job = dpl_Job.SelectedItem.Text;
    
                        dt.Rows[rowIndex]["MyId"] = id;
                        dt.Rows[rowIndex]["MyName"] = name;
                        dt.Rows[rowIndex]["CountryCode"] = countryCode;
                        dt.Rows[rowIndex]["MyCountry"] = country;
                        dt.Rows[rowIndex]["MySalary"] = salary;
                        dt.Rows[rowIndex]["Job"] = job;
                        rowIndex++;
                    }
                    ViewState["CurrentTable"] = dt;
                }
            }

     Demo:

    It might be helpful to do the further coding that you do a code refactoring.

    What's more, you manually assign the value to the gridview but there is already many event handler for data binding stuff. I suggest you using these event handler of the webforms framework so that the coding would be much easier and more readable.

     

    Hope this can help you.

    Best regards,

    Sean

    Monday, April 13, 2020 8:17 AM
  • User-475949336 posted

    <p>Hi Sean Fang</p>
    <p>Your code help me fix remove row very good, thanks your.</p>
    <p>One issue I mention in thread before is responsive (if postback in 'add new' tab then&nbsp; gridview1 in 'list' tab no responsive and&nbsp;contrary, gridview2&nbsp;no responsive), I can't solve, can you save time help me too.</p>
    <p>excuse me, with your UpdateCurrentDataTable(GridView gv), can I use to replace 'SetPreviousData()' in 'add new row' EVENT ?
    </p>
    <p></p>
    <p></p>
    <p></p>
    <p>Best regard!</p>
    Monday, April 13, 2020 9:05 AM
  • User-1330468790 posted

    Hi test010,

     

    test0101

    One issue I mention in thread before is responsive (if postback in 'add new' tab then&nbsp; gridview1 in 'list' tab no responsive and&nbsp;contrary, gridview2&nbsp;no responsive), I can't solve, can you save time help me too.</p>

    Actually, the two datatables are still responsive but you need to ajust the browser's size manually and you will see the responsive effect.

    However, it is still a problem which can be solved by using below code to recalculate the break points and resize the table.

    table.DataTable().columns.adjust().responsive.recalc();

    Moreover, you should do above operation in a specific event of the "tab" - "shown.bs.tab" (Click to see tutorial)

      

    More details, you could refer to below code:

    JS Script: focus on first four functions in yellow background

    I delete few codes so you have to check if they have any meaning for your purpose.

    <script type="text/javascript">
    
            function RememberValue() {        
                var table = $('#<%=GridView2.ClientID%>').DataTable({
                    "destroy": true,
                    'columnDefs': [
                        {
                            
                            //"defaultContent": "-",
                            'targets': [1, 2, 3, 4],
                            'render': function (data, type, row, meta) {
                                if (type === 'display') {
                                    var api = new $.fn.dataTable.Api(meta.settings);
    
                                    var $el = $('input, select, textarea', api.cell({ row: meta.row, column: meta.col }).node());
    
                                    var $html = $(data).wrap('<div/>').parent();
    
                                    if ($el.prop('tagName') === 'INPUT') {
                                        $('input', $html).attr('value', $el.val());
                                        if ($el.prop('checked')) {
                                            $('input', $html).attr('checked', 'checked');
                                        }
                                    } else if ($el.prop('tagName') === 'TEXTAREA') {
                                        $('textarea', $html).html($el.val());
    
                                    } else if ($el.prop('tagName') === 'SELECT') {
                                        $('option:selected', $html).removeAttr('selected');
                                        $('option', $html).filter(function () {
                                            return ($(this).attr('value') === $el.val());
                                        }).attr('selected', 'selected');
                                    }
    
                                    data = $html.html();
                                }
    
                                return data;
                            }
                        }
                    ],
                    'responsive': true
                });
                
            };
           
            
            function SetTabs() {
                var tabName = $("[id*=HiddenTab]").val() != "" ? $("[id*=HiddenTab]").val() : "Listtab";
                $('#dvTab a[href="#' + tabName + '"]').tab('show');
                $('#dvTab a').on('shown.bs.tab', function (e) {
                    $("[id*=HiddenTab]").val($(this).attr("href").replace("#", ""));
                    $($.fn.dataTable.tables(true)).DataTable()
                        .columns.adjust()
                        .responsive.recalc();
                });  
                
            };
    
        </script>
    
        <script type="text/javascript">
            
            
            function pageLoad() {
                SetTabs();
                gridView1DataTable();
                RememberValue();
                
            }
    
            function gridView1DataTable() {
                var table = $('#<%=GridView1.ClientID%>').DataTable({ "destroy": true, "paging": false, "ordering": false, "searching": false, 'responsive': true, "AutoWidth": false });
                
            }
        </script>
    
    
        <script type="text/javascript">
            function onCalendarHidden() {  // Call on Addnew 
                console.log("Begin onCalendarHidden");
                var cal = $find("calendar1");
    
                if (cal._monthsBody) {
                    for (var i = 0; i < cal._monthsBody.rows.length; i++) {
                        var row = cal._monthsBody.rows[i];
                        for (var j = 0; j < row.cells.length; j++) {
                            Sys.UI.DomEvent.removeHandler(row.cells[j].firstChild, "click", call);
                        }
                    }
                }
            }
    
            function onCalendarShown() {
                console.log("Begin onCalendarShown");
                var cal = $find("calendar1");
    
                cal._switchMode("months", true);
    
                if (cal._monthsBody) {
                    for (var i = 0; i < cal._monthsBody.rows.length; i++) {
                        var row = cal._monthsBody.rows[i];
                        for (var j = 0; j < row.cells.length; j++) {
                            Sys.UI.DomEvent.addHandler(row.cells[j].firstChild, "click", call);
                        }
                    }
                }
            }
    
            function call(eventElement) {
                console.log("Begin call(eventElement)");
                var target = eventElement.target;
                switch (target.mode) {
                    case "month":
                        var cal = $find("calendar1");
                        cal._visibleDate = target.date;
                        cal.set_selectedDate(target.date);
                        //cal._switchMonth(target.date);
                        cal._blur.post(true);
                        cal.raiseDateSelectionChanged();
                        break;
                }
            }
        </script>

    Demo:

     

     

    test0101

    excuse me, with your UpdateCurrentDataTable(GridView gv), can I use to replace 'SetPreviousData()' in 'add new row' EVENT ?

    No, as far as I can see, they have different functions.

    • What my method did is simply update the data table in ViewState with the new values from user input.
    • What "SetPreviousData" did is setting the grid view control with the data table in ViewState

    Here I suggest you use the data bound event of the grid view control to complete the data binding stuff instead of using the method 'SetPreviousData()'

    More details, you could see this link for RowDataBound event which you could use to find the drop down list control and assign the value to it.

     

    Hope this can help you.

    Best regards,

    Sean

    Tuesday, April 14, 2020 9:27 AM
  • User-475949336 posted

    Hi Sean Fang

    I update your help and add more code in Page_Load:

     

    if (ViewState["CurrentTable"] != null) 
    
    gridview2 .HeaderRow.TableSection = TableRowSection.TableHeader;

    then gridview1, gridview2  ajust the browser's size very good.

    But, one issue with function RememberValue(): when click 'add new' tab, generate Gridview2, extend one row and input Salary colums, just click 'add row' or 'remove' another row then the 'Salary' will be duplicate (example: before 'Salary' is '123', after add or remove row is '123,123'

    This is my code JS after update in end of CS.aspx:

    <script type="text/javascript">
    
            function RememberValue() {        
                var table = $('#<%=GridView2.ClientID%>').DataTable({
                    "destroy": true,
                    'columnDefs': [
                        {
                            
                            //"defaultContent": "-",
                            'targets': [1, 2, 3, 4],
                            'render': function (data, type, row, meta) {
                                if (type === 'display') {
                                    var api = new $.fn.dataTable.Api(meta.settings);
    
                                    var $el = $('input, select, textarea', api.cell({ row: meta.row, column: meta.col }).node());
    
                                    var $html = $(data).wrap('<div/>').parent();
    
                                    if ($el.prop('tagName') === 'INPUT') {
                                        $('input', $html).attr('value', $el.val());
                                        if ($el.prop('checked')) {
                                            $('input', $html).attr('checked', 'checked');
                                        }
                                    } else if ($el.prop('tagName') === 'TEXTAREA') {
                                        $('textarea', $html).html($el.val());
    
                                    } else if ($el.prop('tagName') === 'SELECT') {
                                        $('option:selected', $html).removeAttr('selected');
                                        $('option', $html).filter(function () {
                                            return ($(this).attr('value') === $el.val());
                                        }).attr('selected', 'selected');
                                    }
    
                                    data = $html.html();
                                }
    
                                return data;
                            }
                        }
    
                    ],
                    'responsive': true
                 });
              
                // I need this for Update original input/select on change in child row
                $('#<%=GridView2.ClientID%> tbody').on('keyup change', '.child input, .child select, .child textarea', function (e) {
                
                    var $el = $(this);
                    var rowIdx = $el.closest('ul').data('dtr-index');
                    var colIdx = $el.closest('li').data('dtr-index');
                    var cell = table.cell({ row: rowIdx, column: colIdx }).node();
                    $('input, select, textarea', cell).val($el.val());
                    if ($el.is(':checked')) {
                        $('input', cell).prop('checked', true);
                    } else {
                        $('input', cell).removeProp('checked');
                    }
                });
            };  
                  
           
            function SetTabs() {
                var tabName = $("[id*=HiddenTab]").val() != "" ? $("[id*=HiddenTab]").val() : "Listtab";
                $('#dvTab a[href="#' + tabName + '"]').tab('show');
                $('#dvTab a').on('shown.bs.tab', function (e) {
                    $("[id*=HiddenTab]").val($(this).attr("href").replace("#", ""));
                    $($.fn.dataTable.tables(true)).DataTable()
                        .columns.adjust()
                        .responsive.recalc();
                });  
                
            };
    
        </script>
    
        <script type="text/javascript">       
            
            function pageLoad() {
                SetTabs();
                gridView1DataTable();
                RememberValue();
                
            }
    
            function gridView1DataTable() {
                var table = $('#<%=GridView1.ClientID%>').DataTable({ "destroy": true, "paging": false, "ordering": false, "searching": false, 'responsive': true, "AutoWidth": false });
                
            }
        </script>

    Tuesday, April 14, 2020 12:11 PM
  • User-1330468790 posted

    Hi test0101,

     

    I think it is caused by the data table responsive feature.

    If you use debugger to check the page, you will find that the data table keeps two "textbox" controls with same "id" and "name" when the area is expanded. One has the property "display:none" and another has not. When you click the "add new" or "remove row" button, it will post back a content combining two textboxes.

    Solution:

    Modify the "AddNewRowToGrid" and  "UpdateCurrentDataTable" method

    private void UpdateCurrentDataTable(GridView gv)
            {
                int rowIndex = 0;
                if (ViewState["CurrentTable"] != null)
                {
                    DataTable dt = (DataTable)ViewState["CurrentTable"];
                    foreach (GridViewRow row in gv.Rows)
                    {
                        Label lbl_Id = (Label)row.FindControl("txtId");
                        TextBox tb_Name = (TextBox)row.FindControl("txtName");
                        DropDownList dpl_Country = (DropDownList)row.FindControl("txtCountry");
                        TextBox tb_Salary = (TextBox)row.FindControl("txtSalary");
                        DropDownList dpl_Job = (DropDownList)row.FindControl("txtJob");
    
                        int id = Convert.ToInt32(lbl_Id.Text);
                        string name = tb_Name.Text;
                        int countryCode = Convert.ToInt32(dpl_Country.SelectedValue);
                        string country = dpl_Country.SelectedItem.Text;
                        string salary = tb_Salary.Text.Split(',').Last();
                        string job = dpl_Job.SelectedItem.Text;
    
                        dt.Rows[rowIndex]["MyId"] = id;
                        dt.Rows[rowIndex]["MyName"] = name;
                        dt.Rows[rowIndex]["CountryCode"] = countryCode;
                        dt.Rows[rowIndex]["MyCountry"] = country;
                        dt.Rows[rowIndex]["MySalary"] = salary;
                        dt.Rows[rowIndex]["Job"] = job;
                        rowIndex++;
                    }
                    ViewState["CurrentTable"] = dt;
                }
            }
     private void AddNewRowToGrid()
            {
    
                if (ViewState["CurrentTable"] != null)
                {
    
                    DataTable dtCurrentTable = (DataTable)ViewState["CurrentTable"];
                    DataRow drCurrentRow = null;
    
                    if (dtCurrentTable.Rows.Count > 0)
                    {
                        drCurrentRow = dtCurrentTable.NewRow();
                        drCurrentRow["MyId"] = dtCurrentTable.Rows.Count + 1;
    
                        //add new row to DataTable
                        dtCurrentTable.Rows.Add(drCurrentRow);
    
                        for (int i = 0; i < dtCurrentTable.Rows.Count - 1; i++)
                        {
    
                            //extract the TextBox values
    
                            TextBox txt_Name = (TextBox)GridView2.Rows[i].Cells[1].FindControl("txtName");
                            Label txt_CountryCode = (Label)GridView2.Rows[i].Cells[2].FindControl("txtCountryCode");
    
                            TextBox txt_Salary = (TextBox)GridView2.Rows[i].Cells[4].FindControl("txtSalary");
    
    
                            dtCurrentTable.Rows[i]["MyName"] = txt_Name.Text;
                            dtCurrentTable.Rows[i]["CountryCode"] = txt_CountryCode.Text;
                            dtCurrentTable.Rows[i]["MySalary"] = txt_Salary.Text.Split(',').Last();
    
                            //extract the DropDownList Selected Items
    
                            DropDownList ddl1 = (DropDownList)GridView2.Rows[i].Cells[3].FindControl("txtCountry");
                            DropDownList ddl2 = (DropDownList)GridView2.Rows[i].Cells[5].FindControl("txtJob");
    
                            // Update the DataRow with the DDL Selected Items
    
                            dtCurrentTable.Rows[i]["MyCountry"] = ddl1.SelectedItem.Text;
                            dtCurrentTable.Rows[i]["Job"] = ddl2.SelectedItem.Text;
                        }
    
                        //Store the current data to ViewState for future reference
                        ViewState["CurrentTable"] = dtCurrentTable;
    
    
                        //Rebind the Grid with the current data to reflect changes
                        GridView2.DataSource = dtCurrentTable;
                        GridView2.DataBind();
    
    
    
                        Mobile_addnew();
                    }
                }
                else
                {
                    Response.Write("ViewState is null");
    
                }
                //Set Previous Data on Postbacks
                SetPreviousData();
            }

      

    The code I provide is the same as before while I hope you have spent time refactoring your code as I suggest you before, it would be better for you understand and learn from your project. Summarizing and improving code sometimes are more important than invariably coding.

      

    Best regards,

    Sean

    Wednesday, April 15, 2020 8:10 AM
  • User-475949336 posted

    Hi Sean Fang

    I updated with your guide, but all values of salary will be wrong, because 'salary' I format it as currency with comma (example 150,298).

    I think you help me find solution: when click 'remove row' or 'add row', the first will collapse all row then remove or add row later.

    I try by add event onClientclick="Collapse_all_rows(); return true;" on 'remove row' and 'add row' buttons

    But it don't run in mobile OR when resize browser in laptop, PC to same as mobile'size.

    function Collapse_all_rows()
    {
    var table = $('#<%=gridview2.ClientID%>').DataTable();
    table.rows('.parent').nodes().to$().find('td:first-child').trigger('click');
    }

    Wednesday, April 15, 2020 9:24 AM
  • User-475949336 posted

    Hi Sean Fang

    How can I resolve this issue? help me with

    best regard!

    Thursday, April 16, 2020 4:02 AM
  • User-1330468790 posted

    Hi test0101,

     

    But it don't run in mobile OR when resize browser in laptop, PC to same as mobile'size.

    I can not reproduce your problem and the code runs well from my side with chrome (I adjust the browser size to test the responsive page).

    However, you said it does not run in mobile so that I think the problem might be located in the code "trigger('click');". Have you tried using trigger('touchstart')?

     

    I updated with your guide, but all values of salary will be wrong, because 'salary' I format it as currency with comma (example 150,298).

    I don't think there is a necessity to format the currency in the textbox since the value should be input by the user. They will not input comma or money symbol. What they should do is just input a sequence of number. Formatting is your responsibility when you want to display it as a number.

    For example, there is a textbox. You are required to input a number for price. The only thing you need to do is to input a number like "123". When you add/save it, then the price will be display in another list/panel with the currency format.

    The reason why I suggest you process the "Salary" string in server side is that the server will always perform the same process. You don't need to consider the mobile stuff.

     

    Hope this can help you.

    Best regards,

    Sean  

    Thursday, April 16, 2020 5:43 AM
  • User-475949336 posted

    Hi Sean Fang

    Could you help me test on your browser as below:

    1- Add this to CS.aspx:

    <asp:TemplateField HeaderText="Remove" HeaderStyle-Width="50px" >
    <ItemTemplate>
    <asp:Button ID="bttRemoveRow" Width="100px" Text="Remove row" runat="server" onclick="bttRemoveRow_Click" onClientclick="Collapse_all_rows(); return true;" Class="btn-primary"></asp:Button>
    </ItemTemplate>
    </asp:TemplateField>

    <asp:Button ID="ButtonAdd" runat="server" Text="Add row" onclick="ButtonAdd_Click" onClientclick="Collapse_all_rows(); return true;" Class="btn-primary" />

    function Collapse_all_rows()
    {
    var table = $('#<%=GridView2.ClientID%>').DataTable();
    table.rows('.parent').nodes().to$().find('td:first-child').trigger('click');
    // table.rows('.parent').nodes().to$().find('td:first-child').trigger('touchstart');  // I try this, it same as 'click' is no action when 'remove' button is hidden
    }

    2- open brower, resize in order to bttRemoveRow button hiddend on brower then click '+' sign to extend one row, input salary,  click '+' sgn on another row, click 'remove' this row. (with me, when click 'remove' it no action). 

    I tested 'Add row' button action nomal on PC, laptop, Mobile. Only 'remove row' no action when it hidden on brower.

    BTW, I agree with you, when input salary no need typing ',' sign, it automatic add by javascript, as my:

    <asp:textbox ID="txtSalary1" onkeyup="isNumberKey(this);" Text='<%# Eval("MySalary1") %>' Width="80px" runat="server"></asp:textbox>

    function isNumberKey(i)
    {
    if (i.value.length > 0){
    i.value = i.value.replace(/[^\d]+/g, ''); // Only number
    i.value = i.value.replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,"); // group for currency
    } }

    so, if I update with guide before (...last indexof ','....) then salary will wrong.

    Thursday, April 16, 2020 6:30 AM
  • User-1330468790 posted

    Hi test0101,

     

    test0101

    1- Add this to CS.aspx:

    <asp:TemplateField HeaderText="Remove" HeaderStyle-Width="50px" >
    <ItemTemplate>
    <asp:Button ID="bttRemoveRow" Width="100px" Text="Remove row" runat="server" onclick="bttRemoveRow_Click" onClientclick="Collapse_all_rows(); return true;" Class="btn-primary"></asp:Button>
    </ItemTemplate>
    </asp:TemplateField>

    <asp:Button ID="ButtonAdd" runat="server" Text="Add row" onclick="ButtonAdd_Click" onClientclick="Collapse_all_rows(); return true;" Class="btn-primary" />

    function Collapse_all_rows()
    {
    var table = $('#<%=GridView2.ClientID%>').DataTable();
    table.rows('.parent').nodes().to$().find('td:first-child').trigger('click');
    // table.rows('.parent').nodes().to$().find('td:first-child').trigger('touchstart');  // I try this, it same as 'click' is no action when 'remove' button is hidden
    }

    I tried these codes and I clicked the add_new button which perform normally from my side.

    You can as below. 

    Could you please tell me which browser you are using to test the code? It may be helpful to reproduce the problem.

     

    test0101

    2- open brower, resize in order to bttRemoveRow button hiddend on brower then click '+' sign to extend one row, input salary,  click '+' sgn on another row, click 'remove' this row. (with me, when click 'remove' it no action). 

    I tested 'Add row' button action nomal on PC, laptop, Mobile. Only 'remove row' no action when it hidden on brower.

    BTW, I agree with you, when input salary no need typing ',' sign, it automatic add by javascript, as my:

    <asp:textbox ID="txtSalary1" onkeyup="isNumberKey(this);" Text='<%# Eval("MySalary1") %>' Width="80px" runat="server"></asp:textbox>

    function isNumberKey(i)
    {
    if (i.value.length > 0){
    i.value = i.value.replace(/[^\d]+/g, ''); // Only number
    i.value = i.value.replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,"); // group for currency
    } }

    Reason why "remove button" not working:

    When you trigger the collapse function, the remove button is also removed.

    About the isNumberKey():

    If you insist on using this function to format the currency text in the text box, you will still need to process the string in the future when you have to use database. You will find that dealing with a number is much easier than dealing with a format string.

    Again, there is no need to format the user input. Instead, you should verify it to check if it is a number.

     

    Best regards,

    Sean

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, April 16, 2020 9:51 AM
  • User-475949336 posted

    Hi Sean Fang

    I replace <asp:Button  with  <asp:LinkButton as below then all perfect on mobile, laptop, pc:

    <asp:TemplateField HeaderText="Remove" HeaderStyle-Width="50px" >
    <ItemTemplate>
    <asp:LinkButton ID="bttRemoveRow" CommandName="Delete" runat="server" Text="Remove row" onclick="bttRemoveRow_Click" onClientclick="Collapse_all_rows(); return true;" />
    </ItemTemplate>
    </asp:TemplateField>

    with <asp:Button ID="ButtonAdd" it running no problem, I keep it with

      <asp:Button ID="ButtonAdd" runat="server" Text="Add row" onclick="ButtonAdd_Click" onClientclick="Collapse_all_rows(); return true;" Class="btn-primary" />

    I'm testing code with firefox and chrome.

    about format number, I want keeping this for clear when typing number salary on textbox.

    I must say that thanks you very much!!!

    Thursday, April 16, 2020 10:03 AM
  • User-1330468790 posted

    Hi test010,

    Glad to hear that the LinkButton works.

    Actually, the LinkButton controls will be rendered as HTML anchor elements and the Button controls will be HTML Input element  of type submit.

    They might take different effect in different browsers.

     

    Best regards,

    Sean 

    Thursday, April 16, 2020 10:35 AM