Thursday, December 18, 2014

Display and update JSON/XML data in tabular format (like gridview, datatable, repeater etc) using jQuery.

 Problem:
Requirement was to get data from database and display in grid. And on click of any link in a grid, I was asked to open a pop up and display controls there. On click of submit button in pop up, I had to update data back in parent gridview. And on final submit, I had to save data in database.

Solution:
I performed following steps to achieve this:
  1. Created a procedure to get all the required data. 
  2. Added a column in procedure to get all the relational data in an XML.
  3. Created a page and displayed data in a grid (grid is having a link button to open pop up). 
  4. Use JsonConvert.SerializeXmlNode(doc) to convert XML data to JSON and set as text of a textbox.(in RowDataBound event) 
  5. Set “style=display:none” attribute of that textbox(to hide that textbox) 
  6. On click of linkbutton in grid, I get data from textbox and created a table from that XML. 
  7. Displayed that table in a div. 
  8. Set height, width, margin and padding of that div using jQuery. 
  9. Provided input fields to manipulate that data and 1 submit button to submit data to parent grid.
  10. On click of Submit, created XML from input fields and update text of textbox in parent grid. And update ID in a hidden field so that we do not need to update all unnecessary data. 
  11. On click of Save button of parent grid, executed server side event.
  12. Read XML value from textbox (depending upon IDs in hidden field). 
  13. Created single XML from all textboxes. 
  14. Created another procedure in database to read that XML and update in tables. 


Following is the complete code aspx and aspx.cs code

JsonXml.aspx


<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
  <title></title>
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js" ></script>
  <script type="text/javascript">

    var winwid = 0;
    $(document).ready(function () {
      var winW = $(window).width();
      $('#dvMain').css('width', winW + 'px');
      $('#dv_1').css('width', winW + 'px');
      $('#dv_2').css('width', (winW - 500) / 2 + 'px');
      $('#dv_3').css('width', (winW - 500) / 2 + 'px');
      $('#dv_4').css('width', winW + 'px');
    });

    function openPopUp(txtid, tempid) {
      var dt = $('#' + txtid).val();

      xmlDoc = $.parseJSON(dt);
      var tbl = $('
'
);
      var tr;
      var chkd = '';
      tr = $('
'
+ "ID: " + tempid + '
');
      $(tbl).append(tr);
      for (var i = 0; i < xmlDoc.root.node.length; i++) {
        chkd = '';
        if (xmlDoc.root.node[i].ID != null) {
          chkd = " checked='checked' ";
        }
        tr = $('
'
+ xmlDoc.root.node[i].xml_node_id + '

'
+ xmlDoc.root.node[i].xml_node_name + ' + chkd + ' />
');
        $(tbl).append(tr);
      }

      $('#dvOptions').html('').append(tbl);
      $('#dvMain').show();
      $('#btnOk').removeAttr("onclick").attr("onclick", "javascript:btnClick('" + txtid + "','" + tempid + "');");
    }
    function btnClick(txtid, tempid) {

      var rows = $('#tblData').find('tr:gt(0)');
      var dt = $('#' + txtid).val();
      var jsn = $.parseJSON(dt);


      for (var i = 0; i < rows.length; i++) {
        if ($(rows[i]).find('td:eq(1) input').is(':checked')) {
          jsn.root.node[i].ID = tempid;
        }
        else {
          jsn.root.node[i].ID = null;
        }
      }
      $('#' + txtid).val(JSON.stringify(jsn));
      setid(tempid);
      closePopUp();
    }
    function setid(id) {
      var vl = $('#<%=hdnIds.ClientID %>').val().split(',');
      if (vl.indexOf(id) < 0) {
        $('#<%=hdnIds.ClientID %>').val($('#<%=hdnIds.ClientID %>').val() + ',' + id);
      }
    }
    function closePopUp() {
      $('#dvMain').hide();
    }
  </script>

</head>
<body>
  <form id="form1" runat="server">
    <div>
      <table>
        <tr>
          <td>
            <asp:Literal ID="ltMsg" runat="server" />
          </td>
        </tr>
        <tr>
          <td>
            <asp:GridView ID="grd" runat="server" AutoGenerateColumns="false"
              Width="100%"
              OnRowDataBound="grd_RowDataBound"
              GridLines="None">
              <Columns>
                <asp:TemplateField HeaderText="Id">
                  <ItemTemplate>
                    <%#Eval("Id") %>
                  </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="data">
                  <ItemTemplate>
                    <asp:TextBox ID="txtData" runat="server" TextMode="MultiLine"></asp:TextBox>
                    <asp:Literal runat="server" ID="ltData"></asp:Literal>
                    <asp:Literal runat="server" ID="Id" Visible="false" Text='<%#Eval("Id") %>'></asp:Literal>
                  </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Name">
                  <ItemTemplate>
                    <%#Eval("Name") %>
                  </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Active">
                  <ItemTemplate>
                    <asp:CheckBox ID="chkActive" runat="server" />
                  </ItemTemplate>
                </asp:TemplateField>
              </Columns>
            </asp:GridView>
          </td>
        </tr>
        <tr>
          <td>
            <asp:Button ID="btn_Save" OnClick="btnSave_Click" Text="Save" runat="server" />
            <asp:HiddenField ID="hdnIds" runat="server" />
          </td>
        </tr>
      </table>
    </div>
    <div id="dvMain" style="display: none; position: fixed; z-index: 99998; background-image: none; top: 0px;">
        <div id="dv_1" style="border: 1px solid; float: left; opacity: 0.01; background-color: rgb(255, 255, 255); height: 100px;"></div>
        <div id="dv_2" style="border: 1px solid; float: left; opacity: 0.01; background-color: rgb(255, 255, 255); height: 470px;"></div>
        <table cellpadding="0" cellspacing="0" border="0" style="border: 1px solid; background: #fff; padding: 20px; z-index: 99999; float: left;">
            <tr>
                <td>
                    <div id="dvOptions" style="height: 370px; width: 430px;">
                    </div>
                </td>
            </tr>
            <tr>
                <td align="center">
                    <input type="button" id="btnOk" value="Submit" class="btn btn-block btn-lg btn-info btn-flt-pad mar-rght-8" /> 
                    <input type="button" id="btnClose" onclick="javascript: closePopUp();" value="Close" class="btn btn-block btn-lg btn-info btn-flt-pad mar-rght-8" />
                    <%-- close--%>
                    </td>
            </tr>
        </table>
        <div id="dv_3" style="border: 1px solid; float: left; opacity: 0.01; background-color: rgb(255, 255, 255); height: 470px;"></div>
        <div id="dv_4" style="border: 1px solid; float: left; opacity: 0.01; background-color: rgb(255, 255, 255); height: 100px;"></div>
    </div>
  </form>
</body>
</html>



JsonXml.aspx.cs

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;

public partial class JsonXml : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        BindData();
       
    }
    protected void btnSave_Click(object sender, EventArgs e)
    {
        XmlDocument rootxml = new XmlDocument();
        XmlDocument doc;
        string json = string.Empty;
        if (!string.IsNullOrEmpty(hdnIds.Value))
        {
            string[] IdArr = hdnIds.Value.Split(',');
            string id;
            XmlElement final_xml = rootxml.CreateElement("final_xml");
            XmlNode importdoc;
            foreach (GridViewRow gvr in grd.Rows)
            {
                id = ((Literal)gvr.FindControl("Id")).Text;
                if (Array.IndexOf(IdArr, id) > -1)
                {
                    json = ((TextBox)gvr.FindControl("txtData")).Text;
                    doc = JsonConvert.DeserializeXmlNode(json);

                    importdoc = rootxml.ImportNode(doc.SelectSingleNode("root"), true);

                    XmlAttribute xId = rootxml.CreateAttribute("Id");
                    xId.Value = id;
                    XmlAttribute xActive = rootxml.CreateAttribute("IsActive");
                    xActive.Value = ((CheckBox)gvr.FindControl("chkActive")).Checked.ToString();
                    importdoc.Attributes.Append(xId);
                    importdoc.Attributes.Append(xActive);
                    final_xml.AppendChild(importdoc);

                }
            }
            //function_to_call_database_and_save_data_from_xml(final_xml.OuterXml);
            hdnIds.Value = "";
            BindData();
            ltMsg.Text = "Congratulations. All data has been saved to database.";
        }
    }
    protected void grd_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            CheckBox chkActive = (CheckBox)e.Row.FindControl("chkActive");
            chkActive.Checked = (Convert.ToString(DataBinder.Eval(e.Row.DataItem, "IsActive")) == "Y");
            TextBox txtData = (TextBox)e.Row.FindControl("txtData");
            Literal ltData = (Literal)e.Row.FindControl("ltData");
            string xml = Convert.ToString(DataBinder.Eval(e.Row.DataItem, "data"));
            string id = Convert.ToString(DataBinder.Eval(e.Row.DataItem, "Id"));
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);
            string jsonText = JsonConvert.SerializeXmlNode(doc);

            txtData.Text = jsonText;
            txtData.Attributes.Add("style", "display:none;");
            chkActive.Attributes.Add("onclick", "javascript:setid('" + id + "');");
        }
    }
    void BindData()
    {
        DataTable dt = new DataTable();
        DataColumn dc1 = new DataColumn("Id");
        dt.Columns.Add(dc1);
        DataColumn dc2 = new DataColumn("Name");
        dt.Columns.Add(dc2);
        DataColumn dc3 = new DataColumn("Data");
        dt.Columns.Add(dc3);
        DataColumn dc4 = new DataColumn("IsActive");
        dt.Columns.Add(dc4);
        DataRow dr;
        for (int i = 5; i < 10; i++)
        {
            dr = dt.NewRow();
            dr["Id"] = i;
            dr["Name"] = Guid.NewGuid().ToString().Substring(0, 4);
            dr["Data"] = "<root><node><xml_node_id>4</xml_node_id><xml_node_name>xml node name 1</xml_node_name></node><node><xml_node_id>5</xml_node_id><xml_node_name>xml node name 2</xml_node_name></node><node><xml_node_id>6</xml_node_id><xml_node_name>xml node name 3</xml_node_name></node><node><xml_node_id>7</xml_node_id><xml_node_name>xml node name 4</xml_node_name></node><node><xml_node_id>8</xml_node_id><xml_node_name>xml node name 5</xml_node_name></node><node><xml_node_id>9</xml_node_id><xml_node_name>xml node name 6</xml_node_name></node><node><xml_node_id>10</xml_node_id><xml_node_name>xml node name 7</xml_node_name></node><node><xml_node_id>11</xml_node_id><xml_node_name>xml node name 8</xml_node_name></node><node><xml_node_id>12</xml_node_id><xml_node_name>xml node name 9</xml_node_name></node><node><xml_node_id>13</xml_node_id><xml_node_name>xml node name 10</xml_node_name></node><node><xml_node_id>14</xml_node_id><xml_node_name>xml node name 11</xml_node_name></node><node><xml_node_id>15</xml_node_id><xml_node_name>xml node name 12</xml_node_name></node><node><xml_node_id>16</xml_node_id><xml_node_name>xml node name 13</xml_node_name></node><node><xml_node_id>17</xml_node_id><xml_node_name>xml node name 14</xml_node_name></node></root>";
            dr["IsActive"] = "Y";
            dt.Rows.Add(dr);
        }
        grd.DataSource = dt;
        grd.DataBind();
    }
}

Wednesday, December 17, 2014

jQuery: changes are not displaying in html? Use prop(), end() and change()

Problem:
Some time it happens like we use jQuery to machine some changes (set value, change attribute value, selected index change, checkbox/radio-button check change) on page, and those changes do not reflect on screen. If you inspect/check those elements using developer tools (firebug, IE Developer toolbar, Chrome developer tools etc), you’ll find that value is perfectly assigned to the element. But still changes do not display on the screen.

Solution:
Do not use .attr(‘attribute’,’value’) to set some attribute value. Use prop and end instead and call the change function to display value.

Correct but not displaying value on page:
      $('#checkbox_id').attr('checked', true);

Correct and displaying value on page:


        $('#checkbox_id').prop('checked', true).end().change();

checkboxlist/radiobuttonlist filter textbox using jQuery (with result count)

Hi Developers,

following is the complete single code to filter large list of checkboxes and radiobuttons. I created a hashtable and bind that to radiobuttonlist and checkboxlist. we can use any data source(collection, dataset, datatable etc) instead. same code will work with other data listing controls(repeater, datalist and gridview).

test.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="test1.aspx.cs" Inherits="test1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
  <title>nitindhiman.blogspot.com</title>
  <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js" type="text/javascript"></script>
  <script type="text/javascript">
    function textChange(e, txtbox, cls) {
      if (!(/[^A-Za-z0-9 ]/.test(String.fromCharCode(e.keyCode))) || e.keyCode == 8) {
        var text = $(txtbox).val().toLowerCase();
        var node = '';
        var count = 0;
        $('#td_' + cls + ' table tr').each(function () {
          node = $(this).text().toLowerCase();
          if (node.match(text) == null)
            $(this).hide();
          else {
            $(this).show();
            count++;
          }
        });
        $('#sp_' + cls).html((count) + ' items');
      }
    }
  </script>
</head>
<body>
  <form id="form1" runat="server">
    <div>
      <table>
        <tr>
          <td >
            <asp:TextBox ID="txtChkFilter" runat="server" onkeyup="javascript:textChange(event,this,'Chk');"></asp:TextBox>
            <span id="sp_Chk"><%=ChkCount%></span>
          </td>
          <td >
            <asp:TextBox ID="txtRadioFilter" runat="server" onkeyup="javascript:textChange(event,this,'Rdo');"></asp:TextBox>
            <span id="sp_Rdo"><%=RdoCount%></span>
          </td>
        </tr>
        <tr>
          <td>
            <div id="td_Chk">
              <asp:CheckBoxList ID="cblChkOption" DataValueField="Key" DataTextField="Value" runat="server">
              </asp:CheckBoxList>
            </div>
          </td>
          <td>
            <div id="td_Rdo">
              <asp:RadioButtonList ID="cblRdoOption" DataValueField="Key" DataTextField="Value" runat="server">
              </asp:RadioButtonList>
            </div>
          </td>
        </tr>
      </table>
    </div>
  </form>
</body>
</html>

test.aspx.cs

using System;
using System.Collections;

public partial class test1 : System.Web.UI.Page
{
    protected string ChkCount = string.Empty;
    protected string RdoCount = string.Empty;
    protected void Page_Load(object sender, EventArgs e)
    {
        binddate();
    }
    void binddate()
    {
        Hashtable ht = new Hashtable();
        ht.Add(1, "System");
        ht.Add(2, "Collections");
        ht.Add(3, "Generic");
        ht.Add(4, "Linq");
        ht.Add(5, "Web");
        ht.Add(6, "UI");
        ht.Add(7, "WebControls");
        ChkCount = ht.Count + " items";
        RdoCount = ht.Count + " items";
        cblChkOption.DataSource = ht;
        cblChkOption.DataBind();
        cblRdoOption.DataSource = ht;
        cblRdoOption.DataBind();
    }
}