Apr 25, 2012, 4:02 PM
Ext.Net 1.3 - RowExpander and RowEditor . Saving data in database. (FOR NEWBIES ONLY)
Hello guys,
I am new to ext.net
Recently I downloaded ext.net 1.3 .
I implemented the grid panel with sorting functionality.
Then I liked the rowexpander plugin with the + sign. On click the details open and you can save the data.
I needed a way to pass only the current selected row for update. And not the entire data.
But the method which I used , passed the entire grid rows including the one selected.
So the issue was how to let my handler know that which record is to be updated and discard/ignore the rest.
I solved this issue.
First I will paste my aspx code having GridPanel, Store , RowExpander and Roweditor plugins :
My aspx file : MyDocuments.aspx
My aspx.cs file : MyDocuments.aspx.cs
My handlers : "Documents.ashx" for read and "DocumentSave.ashx" for POST.
Explanation : As you have seen in the code, in the <store> I used the <UpdateProxy> and a <ext:HttpWriteProxy
In the RowExpander plugin I used <Listener> for <Button> clicks
The #{GridPanel1}.submitData(); is for saving data to database i.e.invoking the POST method.
Explanation of DocumentSave.ashx with code
+++++++++++++++++++++++++++++++++
++++++++++
So here I used the value "idvalue" to get the id of the edited row
Then I used the Request["data"] from the current context.
I took this data in a Dictionary object. And then used a counter to match the "idvalue" value.
If matched, only that data will be saved in database. Others will be ignored.
Some points to note
+++++++++++++++
I had created Document.cs class in App_Code which was used by my reader.
So make sure you create that.
In case if anyone is interested to learn about reading the data, I will post that too.
Enjoy!!!
Khush
I am new to ext.net
Recently I downloaded ext.net 1.3 .
I implemented the grid panel with sorting functionality.
Then I liked the rowexpander plugin with the + sign. On click the details open and you can save the data.
I needed a way to pass only the current selected row for update. And not the entire data.
But the method which I used , passed the entire grid rows including the one selected.
So the issue was how to let my handler know that which record is to be updated and discard/ignore the rest.
I solved this issue.
First I will paste my aspx code having GridPanel, Store , RowExpander and Roweditor plugins :
My aspx file : MyDocuments.aspx
My aspx.cs file : MyDocuments.aspx.cs
My handlers : "Documents.ashx" for read and "DocumentSave.ashx" for POST.
<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" CodeFile="MyDocuments.aspx.cs" Inherits="MyDocuments" %>
<%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
<asp:Content ID="Content2" ContentPlaceHolderID="head" runat="Server">
<link type="text/css" href="css/black-tie/jquery-ui-1.8.16.custom.css" rel="stylesheet" />
<script type="text/javascript" src="js/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.8.16.custom.min.js"></script>
<link href="resources/css/examples.css" rel="stylesheet" type="text/css" />
<style type="text/css">
.style1
{
width: 183px;
text-align: right;
padding-right: 20px;
}
.style2
{
width: 194px;
}
</style>
<style type="text/css">
.mycalendar
{
display: none;
}
#progressBackgroundFilter
{
position: absolute;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
overflow: hidden;
padding: 0;
margin: 0;
background-color: #000;
filter: alpha(opacity=50);
opacity: 0.5;
z-index: 1000;
}
#processMessage
{
position: absolute;
top: 30%;
left: 43%;
padding: 10px;
width: 14%;
z-index: 1001;
background-color: #fff;
}
.style3
{
height: 21px;
}
.style4
{
width: 222px;
}
.style5
{
width: 32%;
}
.style6
{
height: 21px;
width: 52%;
}
.style7
{
width: 52%;
}
.style9
{
width: 82px;
}
.style11
{
width: 155px;
}
.style12
{
width: 92px;
}
</style>
<style type="text/css">
.template {
color: #fff;
background-color: gray;
}
.white-footer .x-panel-footer{
background-color: white !important;
}
</style>
<script type="text/javascript">
var template = '<span style="color:{0};">{1}</span>';
var change = function (value) {
return String.format(template, (value > 0) ? "green" : "red", value);
};
var pctChange = function (value) {
return String.format(template, (value > 0) ? "green" : "red", value + "%");
};
</script>
<script type="text/javascript">
$(function() {
// Tabs
$('#tabs').tabs();
});
</script>
</asp:Content>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
<table width="100%">
<tr>
<td>
<h2 runat="server" id="divMilestones">
Manage Documents
</h2>
</td>
<td>
<asp:ImageButton Style="float: right;" runat="server" ID="lnkbtnclose" ToolTip="Close Form"
ImageUrl="images/close.jpg" OnClick="lnkbtnclose_Click" CausesValidation="False" />
</td>
</tr>
</table>
<div class="gt-form gt-content-box gt-form-row">
<div class="gt-table-controls clearfix">
<table style="width: 91%">
<tr>
<td>
<div id="tabs">
<ul>
<li><a href="#tabs-1">View/Edit</a></li>
<li><a href="#tabs-2">Folder Management</a></li>
</ul>
</div>
<div id="tabs-1">
<ext:ResourceManager ID="ResourceManager1" runat="server" />
<ext:GridPanel
ID="GridPanel1"
runat="server"
Title="Documents"
Frame="true"
AutoExpandColumn="filename"
Height="400" Width="731">
<Store>
<ext:Store ID="Store1" runat="server" RemoteSort="true">
<Proxy>
<ext:HttpProxy Method="GET" Url="Documents.ashx" />
</Proxy>
<UpdateProxy>
<ext:HttpWriteProxy Json="true" Method="POST" Url="DocumentSave.ashx" />
</UpdateProxy>
<WriteBaseParams>
<ext:Parameter Name="idvalue" Value="#{Store1}.indexOf(#{RowEditor1}.record)" Mode="Raw" />
</WriteBaseParams>
<AutoLoadParams>
<ext:Parameter Name="start" Value="={0}" />
<ext:Parameter Name="limit" Value="={5}" />
</AutoLoadParams>
<Reader>
<ext:JsonReader Root="Data" TotalProperty="TotalRecords">
<Fields>
<ext:RecordField Name="id" Type="Int" />
<ext:RecordField Name="filename" />
<ext:RecordField Name="size" Type="Float" />
<ext:RecordField Name="uploadedon" Type="Date" />
</Fields>
</ext:JsonReader>
</Reader>
<Listeners>
<Save Handler="Ext.Msg.alert('Submit','Submit successful');" />
<SaveException Handler="Ext.Msg.alert('Submit','Submit failure: ' + e.message);" />
</Listeners>
<SortInfo Field="filename" Direction="ASC" />
</ext:Store>
</Store>
<ColumnModel runat="server">
<Columns>
<ext:Column ColumnID="id" Header="ID" DataIndex="id" Width="50" Sortable="true" />
<ext:Column Header="File Name" DataIndex="filename" Width="80" />
<ext:Column Header="Size" DataIndex="size" Width="50" />
<ext:DateColumn Header="Uploaded On" DataIndex="uploadedon" Width="95" Format="yyyy-MM-dd" />
</Columns>
</ColumnModel>
<SelectionModel>
<ext:RowSelectionModel ID="RowSelectionModel1" SingleSelect="true" runat="server" />
</SelectionModel>
<Plugins>
<ext:RowExpander ID="RowExpander" runat="server">
<Component>
<ext:FormPanel
ID="RowEditor1"
runat="server"
Padding="6"
Height="180"
Border="false"
Layout="form"
ForceLayout="true"
ButtonAlign="Right"
Cls="white-footer">
<Items>
<ext:TextField ID="TextField1"
runat="server"
DataIndex="filename"
FieldLabel="File Name"
Width="250"
/>
<ext:NumberField ID="NumberField2"
runat="server"
DataIndex="size"
FieldLabel="Size"
Width="150"
/>
<ext:DateField ID="DateField1"
runat="server"
DataIndex="uploadedon"
FieldLabel="Upload Date"
Width="150"
/>
</Items>
<Buttons>
<ext:Button ID="Button1" runat="server" Text="Save" Icon="Disk">
<Listeners>
<Click Handler="#{RowEditor1}.getForm().updateRecord(#{RowEditor1}.record);
#{RowExpander}.collapseRow(#{Store1}.indexOf(#{RowEditor1}.record));
#{Store1}.commitChanges();
#{GridPanel1}.submitData();
" />
</Listeners>
</ext:Button>
<ext:Button ID="Button2" runat="server" Text="Cancel" Icon="Decline">
<Listeners>
<Click Handler="#{RowExpander}.collapseRow(#{Store1}.indexOf(#{RowEditor1}.record));" />
</Listeners>
</ext:Button>
</Buttons>
</ext:FormPanel>
</Component>
<Listeners>
<Expand Handler="#{RowEditor1}.record = record; #{RowEditor1}.getForm().loadRecord(record);" />
</Listeners>
</ext:RowExpander>
</Plugins>
<BottomBar>
<ext:PagingToolbar ID="PagingToolbar1"
runat="server"
PageSize="5"
DisplayInfo="true"
DisplayMsg="Displaying docs {0} - {1} of {2}"
EmptyMsg="No docs to display"
/>
</BottomBar>
<LoadMask ShowMask="true" />
</ext:GridPanel>
</div>
<%--<div id="tabs">
<ul>
<li><a href="#tabs-1">View</a></li>
<li><a href="#tabs-2">Upload</a></li>
<li><a href="#tabs-3">Delete</a></li>
<li><a href="#tabs-3">Add Folder</a></li>
</ul>
</div>
<div id="tabs-1">
</div>--%>
</td>
</tr>
</table>
</div>
</div>
</asp:Content>
Now I will explain you the logic of saving the records only. Since getting the data is easy stuff. And you can handle it.Explanation : As you have seen in the code, in the <store> I used the <UpdateProxy> and a <ext:HttpWriteProxy
<UpdateProxy>
<ext:HttpWriteProxy Json="true" Method="POST" Url="DocumentSave.ashx" />
</UpdateProxy>
<WriteBaseParams>
<ext:Parameter Name="idvalue" Value="#{Store1}.indexOf(#{RowEditor1}.record)" Mode="Raw" />
</WriteBaseParams>
So the "idvalue" is passed to the datahandler.In the RowExpander plugin I used <Listener> for <Button> clicks
<Listeners>
<Click Handler="#{RowEditor1}.getForm().updateRecord(#{RowEditor1}.record);
#{RowExpander}.collapseRow(#{Store1}.indexOf(#{RowEditor1}.record));
#{Store1}.commitChanges();
#{GridPanel1}.submitData();
" />
</Listeners>
Please take care to include #{Store1}.commitChanges(); else your data will not be saved in the grid.The #{GridPanel1}.submitData(); is for saving data to database i.e.invoking the POST method.
Explanation of DocumentSave.ashx with code
+++++++++++++++++++++++++++++++++
<%@ WebHandler Language="C#" Class="DocumentSave" %>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using Ext.Net;
using Newtonsoft.Json;
using System.IO;
using System.Data;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Configuration;
public class DocumentSave : IHttpHandler {
public string conn=ConfigurationManager.ConnectionStrings["Connection"].ToString();
public int id = 0;
public void ProcessRequest (HttpContext context) {
//context.Response.ContentType = "text/plain";
//context.Response.Write("Hello World");
Response sr = new Response(true);
string value = string.Empty;
string x="";
if (!string.IsNullOrEmpty(context.Request["idvalue"]))
{
id = int.Parse(context.Request["idvalue"]);
}
string json = context.Request["data"];
Dictionary<string, string>[] documents = JSON.Deserialize<Dictionary<string, string>[]>(json);
//bool addHeader = true;
int _ctr = 0;
bool _isrecord = false;
foreach (Dictionary<string, string> row in documents)
{
int _id = 0;
string _filename = "";
DateTime _uploaddate = DateTime.Today;
foreach (KeyValuePair<string, string> keyValuePair in row)
{
if (id == _ctr)
_isrecord = true;
else
break;
if (_isrecord == true)
{
if (keyValuePair.Key.ToString() == "id")
_id = int.Parse(keyValuePair.Value);
if (keyValuePair.Key.ToString() == "filename")
_filename = keyValuePair.Value;
if (keyValuePair.Key.ToString() == "uploadedon")
_uploaddate = DateTime.Parse(keyValuePair.Value);
}
}
if (_isrecord == true)
{
string _qry = "update Documents set filename='" + _filename.Replace("'", "''") + "',";
_qry += "uploadedon=convert(varchar(19),'" + _uploaddate.Year.ToString() + "-" + _uploaddate.Month.ToString() + "-" + _uploaddate.Day.ToString() + " 00:00:00',120) ";
_qry += "where id='" + _id.ToString() + "'";
SqlConnection cn = new SqlConnection(conn);
cn.Open();
try
{
SqlCommand cmd = cn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = _qry;
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
sr.Success = false;
sr.Message = ex.Message.ToString();
}
finally
{
cn.Close();
cn = null;
}
break;
}
else
_ctr++;
}
sr.Write();
}
public bool IsReusable {
get {
return false;
}
}
}
Explanation++++++++++
So here I used the value "idvalue" to get the id of the edited row
Then I used the Request["data"] from the current context.
I took this data in a Dictionary object. And then used a counter to match the "idvalue" value.
If matched, only that data will be saved in database. Others will be ignored.
Some points to note
+++++++++++++++
I had created Document.cs class in App_Code which was used by my reader.
So make sure you create that.
In case if anyone is interested to learn about reading the data, I will post that too.
Enjoy!!!
Khush
Last edited by geoffrey.mcgill; Apr 25, 2012 at 7:21 PM.
Reason: please use [CODE] tags