[CLOSED] Export Data From Grid Panel via AJAX with mask

  1. #1

    [CLOSED] Export Data From Grid Panel via AJAX with mask

    Hello,

    I was looking at your export from grid example here: https://examples1.ext.net/#/GridPane...ort_Data_Ajax/

    In the source code, there is this commented out bit:

     <%--<p>Limitations of ajax file downloading: success/failure events don't fired. Therefore the mask is impossible.</p>--%>
    Accordingly, your example has only the LoadMask set on it, not the SaveMask.

    My questions are as follows:

    1) Although it is commented out, I assume this limitation is still true? My assumption is that the response content type is no longer text/html, therefore there is no possibility for the client code to get a status result and therefore not possible to create success/failure events?

    If so, I've tried an alternative approach that may be useful for some people in some scenarios: I added a SaveMask (full example below) as follows:

     <SaveMask ShowMask="true" Msg="Submitting data..." />
    On its own it will not hide once you do an export, so in the submitValue JavaScript handler I added a setTimeout, so that after 1 second the Save Mask is hidden:

         var submitValue = function (grid, hiddenFormat, format) {
             hiddenFormat.setValue(format);
             grid.submitData(false);
             setTimeout(function () {
                 grid.saveMask.hide();
             }, 1000);
         };
    It is not perfect (some operations could take more than a second, for example) but might be enough for my needs.

    Also there is subtle browser behaviour difference (all on Windows Server 2008) though I don't think it is a big deal:

    • Firefox 3.6.8 and 4.0 beta (latest), Chrome and Safari - mask goes away after 1 second from clicking the export button
    • IE8 - mask goes away after 1 second from the download dialog being dismissed

    2) Is there a cleaner way than using the setTimeout? Perhaps another feature of ExtJs that I have missed :)

    Here is the full code for your example with both modifications added in for reference:

    <%@ Page Language="C#" %>
      
     <%@ Import Namespace="System.Xml.Xsl" %>
     <%@ Import Namespace="System.Xml" %>
     <%@ Import Namespace="System.Linq" %>
      
     <%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
      
     <script runat="server">
         private object[] TestData
         {
             get
             {
                 DateTime now = DateTime.Now;
      
                 return new object[]
                 {
                     new object[] { 1, "3m Co", 71.72, 0.02, 0.03, now },
                     new object[] { 2, "Alcoa Inc", 29.01, 0.42, 1.47, now },
                     new object[] { 3, "Altria Group Inc", 83.81, 0.28, 0.34, now },
                     new object[] { 4, "American Express Company", 52.55, 0.01, 0.02, now },
                     new object[] { 5, "American International Group, Inc.", 64.13, 0.31, 0.49, now },
                     new object[] { 6, "AT&T Inc.", 31.61, -0.48, -1.54, now },
                     new object[] { 7, "Boeing Co.", 75.43, 0.53, 0.71, now },
                     new object[] { 8, "Caterpillar Inc.", 67.27, 0.92, 1.39, now },
                     new object[] { 9, "Citigroup, Inc.", 49.37, 0.02, 0.04, now },
                     new object[] { 10, "E.I. du Pont de Nemours and Company", 40.48, 0.51, 1.28, now },
                     new object[] { 11, "Exxon Mobil Corp", 68.1, -0.43, -0.64, now },
                     new object[] { 12, "General Electric Company", 34.14, -0.08, -0.23, now },
                     new object[] { 13, "General Motors Corporation", 30.27, 1.09, 3.74, now },
                     new object[] { 14, "Hewlett-Packard Co.", 36.53, -0.03, -0.08, now },
                     new object[] { 15, "Honeywell Intl Inc", 38.77, 0.05, 0.13, now },
                     new object[] { 16, "Intel Corporation", 19.88, 0.31, 1.58, now },
                     new object[] { 17, "International Business Machines", 81.41, 0.44, 0.54, now },
                     new object[] { 18, "Johnson & Johnson", 64.72, 0.06, 0.09, now },
                     new object[] { 19, "JP Morgan & Chase & Co", 45.73, 0.07, 0.15, now },
                     new object[] { 20, "McDonald\"s Corporation", 36.76, 0.86, 2.40, now },
                     new object[] { 21, "Merck & Co., Inc.", 40.96, 0.41, 1.01, now },
                     new object[] { 22, "Microsoft Corporation", 25.84, 0.14, 0.54, now },
                     new object[] { 23, "Pfizer Inc", 27.96, 0.4, 1.45, now },
                     new object[] { 24, "The Coca-Cola Company", 45.07, 0.26, 0.58, now },
                     new object[] { 25, "The Home Depot, Inc.", 34.64, 0.35, 1.02, now },
                     new object[] { 26, "The Procter & Gamble Company", 61.91, 0.01, 0.02, now },
                     new object[] { 27, "United Technologies Corporation", 63.26, 0.55, 0.88, now },
                     new object[] { 28, "Verizon Communications", 35.57, 0.39, 1.11, now },
                     new object[] { 29, "Wal-Mart Stores, Inc.", 45.45, 0.73, 1.63, now }
                 };
             }
         }
         
         protected void Store1_RefreshData(object sender, StoreRefreshDataEventArgs e)
         {
             this.Store1.DataSource = this.TestData;
             this.Store1.DataBind();
         }
      
         protected void Store1_RecordUpdated(object sender, AfterRecordUpdatedEventArgs e)
         {
             // This event is fired once for each Record that is Updated.
      
             var company = new { 
                 Name = e.NewValues["company"], 
                 Price = e.NewValues["price"], 
                 LastChange = e.NewValues["lastChange"] 
             };
      
             string tpl = "Name: {0}, Price: {1}, LastChange: {2}<br />";
             this.Label1.Html += string.Format(tpl, company.Name, company.Price, company.LastChange);
         }
      
         protected void Store1_Submit(object sender, StoreSubmitDataEventArgs e)
         {
             string format = this.FormatType.Value.ToString();
      
             XmlNode xml = e.Xml;
      
             this.Response.Clear();
             
             switch(format)
             {
                 case "xml":
                         string strXml = xml.OuterXml;
                         this.Response.AddHeader("Content-Disposition", "attachment; filename=submittedData.xml");
                         this.Response.AddHeader("Content-Length", strXml.Length.ToString());
                         this.Response.ContentType = "application/xml";
                         this.Response.Write(strXml);
                     break;
                 
                 case "xls":
                         this.Response.ContentType = "application/vnd.ms-excel";
                         this.Response.AddHeader("Content-Disposition", "attachment; filename=submittedData.xls");
                         XslCompiledTransform xtExcel = new XslCompiledTransform();
                         xtExcel.Load(Server.MapPath("Excel.xsl"));
                         xtExcel.Transform(xml, null, Response.OutputStream);
      
                     break;
      
                 case "csv":
                     this.Response.ContentType = "application/octet-stream";
                     this.Response.AddHeader("Content-Disposition", "attachment; filename=submittedData.csv");
                     XslCompiledTransform xtCsv = new XslCompiledTransform();
                     xtCsv.Load(Server.MapPath("Csv.xsl"));
                     xtCsv.Transform(xml, null, Response.OutputStream);
      
                     break;
             }
             this.Response.End();
         }
     </script>
      
     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      
     <html xmlns="http://www.w3.org/1999/xhtml">
     <head id="Head1" runat="server">
         <title>Export Data from GridPanel into XML, Excel or CSV using an AjaxRequest - Ext.NET Examples</title>
         <link href="../../../../resources/css/examples.css" rel="stylesheet" type="text/css" />    
         
         <script type="text/javascript">
             var submitValue = function (grid, hiddenFormat, format) {
                 hiddenFormat.setValue(format);
                 grid.submitData(false);
                 setTimeout(function () {
                     grid.saveMask.hide();
                 }, 1000);
             };
      
             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>
     </head>
     <body>
         <form id="Form1" runat="server">
             <ext:ResourceManager ID="ResourceManager1" runat="server" />
             
             <h1>Export Data from GridPanel into XML, Excel or CSV using an AjaxRequest</h1>
             
             <%--<p>Limitations of ajax file downloading: success/failure events don't fired. Therefore the mask is impossible.</p>--%>
             
             <ext:Hidden ID="FormatType" runat="server" />
             
             <ext:Store 
                 ID="Store1" 
                 runat="server" 
                 OnAfterRecordUpdated="Store1_RecordUpdated" 
                 OnRefreshData="Store1_RefreshData"
                 OnSubmitData="Store1_Submit"
                 
                 RemoteSort="true">
                 <DirectEventConfig IsUpload="true" />
                 <Proxy>
                     <ext:PageProxy />
                 </Proxy>
                 <Reader>
                     <ext:ArrayReader IDProperty="company">
                         <Fields>
                             <ext:RecordField Name="id" Type="Int" />
                             <ext:RecordField Name="company" />
                             <ext:RecordField Name="price" Type="Float" />
                             <ext:RecordField Name="change" Type="Float" />
                             <ext:RecordField Name="pctChange" Type="Float" />
                             <ext:RecordField Name="lastChange" Type="Date" />
                         </Fields>
                     </ext:ArrayReader>
                 </Reader>
             </ext:Store>
             
             <ext:GridPanel 
                 ID="GridPanel1" 
                 runat="server" 
                 StoreID="Store1" 
                 StripeRows="true"
                 Title="Array Grid" 
                 Width="600" 
                 Height="290"
                 AutoExpandColumn="Company">
                 <TopBar>
                     <ext:Toolbar ID="Toolbar1" runat="server">
                         <Items>
                             <ext:ToolbarFill ID="ToolbarFill1" runat="server" />
                             <ext:Button ID="Button2" runat="server" Text="To XML" Icon="PageCode">
                                 <Listeners>
                                     <Click Handler="submitValue(#{GridPanel1}, #{FormatType}, 'xml');" />
                                 </Listeners>
                             </ext:Button>
                             
                             <ext:Button ID="Button3" runat="server" Text="To Excel" Icon="PageExcel">
                                 <Listeners>
                                     <Click Handler="submitValue(#{GridPanel1}, #{FormatType}, 'xls');" />
                                 </Listeners>
                             </ext:Button>
                             
                             <ext:Button ID="Button4" runat="server" Text="To CSV" Icon="PageAttach">
                                 <Listeners>
                                     <Click Handler="submitValue(#{GridPanel1}, #{FormatType}, 'csv');" />
                                 </Listeners>
                             </ext:Button>
                         </Items>
                     </ext:Toolbar>
                 </TopBar>
                 <ColumnModel ID="ColumnModel1" runat="server">
                     <Columns>
                         <ext:Column 
                             ColumnID="Company" 
                             Header="Company" 
                             Width="160" 
                             Sortable="true" 
                             DataIndex="company">
                             <Editor>
                                 <ext:TextField ID="TextField1" runat="server" />
                             </Editor>
                         </ext:Column>
                         <ext:Column Header="Price" Width="75" DataIndex="price">
                             <Renderer Format="UsMoney" />
                             <Editor>
                                 <ext:TextField ID="TextField2" runat="server" />
                             </Editor>
                         </ext:Column>
                         <ext:Column Header="Change" Width="75" DataIndex="change" />
                         <ext:Column Header="Change" Width="75" DataIndex="pctChange" />
                         <ext:DateColumn Header="Last Updated" Width="85" DataIndex="lastChange" Format="HH:mm:ss" />
                     </Columns>
                 </ColumnModel>
                 <SelectionModel>
                     <ext:RowSelectionModel ID="RowSelectionModel1" runat="server" />
                 </SelectionModel>
                 <LoadMask ShowMask="true" />
                 <SaveMask ShowMask="true" Msg="[Save Mask] Submitting data..." />
             </ext:GridPanel>
             
             <ext:Label ID="Label1" runat="server" />
         </form>
     </body>
     </html>
    Last edited by Daniil; Sep 10, 2010 at 10:53 AM. Reason: [CLOSED]
  2. #2
    1) Although it is commented out, I assume this limitation is still true? My assumption is that the response content type is no longer text/html, therefore there is no possibility for the client code to get a status result and therefore not possible to create success/failure events?
    Hello, anup!

    Yes, this is still true. But I'm not sure about the reasons of this limitation. I think someone from Dev team will make this question clear soon.


    Also there is subtle browser behaviour difference (all on Windows Server 2008) though I don't think it is a big deal:

    • Firefox 3.6.8 and 4.0 beta (latest), Chrome and Safari - mask goes away after 1 second from clicking the export button
    • IE8 - mask goes away after 1 second from the download dialog being dismissed
    I think it's because of the difference between "File download" dialogs in these browsers. It's the same as the difference between Ext.Msg.alert and javascript core alert. The Ext alert dialog doesn't stop executing a javascript code but the second one stops.

    2) Is there a cleaner way than using the setTimeout? Perhaps another feature of ExtJs that I have missed
    There is the defer function in ExtJS for that.
    http://dev.sencha.com/deploy/dev/doc...n&member=defer

    So, in your example you can use

    Example
    grid.saveMask.hide.defer(1000, grid.saveMask);
    instead of

    setTimeout(function() {
        grid.saveMask.hide();
    }, 1000);
    But if look into the source code of defer function you'll see the setTimeout there.
  3. #3
    Quote Originally Posted by Daniil View Post
    There is the defer function in ExtJS for that.
    http://dev.sencha.com/deploy/dev/doc...n&member=defer

    So, in your example you can use

    Example
    grid.saveMask.hide.defer(1000, grid.saveMask);
    instead of

    setTimeout(function() {
        grid.saveMask.hide();
    }, 1000);
    But if look into the source code of defer function you'll see the setTimeout there.
    Many thanks for that tip! In my particular situation here, I can stick with setTimeout as I don't need to do much else, but knowing about the defer method will help me in some other situations as its use of createDelegate looks quite useful where the additional enclosure is needed.
  4. #4
    Hello!

    It's nice to help you:)

    By the way I'm curious is there a way to catch event from a FIle Download dialog...
  5. #5
    Daniil,

    I don't think it is possible to catch the event of a file download dialog because the response content type is handled by the browser directly and therefore not passed to the DOM or JavaScript.

    Unless specific browsers have specific APIs for this... but I am not aware of that.

    Did a quick google around and Rick Strahl (who has a reasonably popular asp.net blog) answers this to the same effect (albeit in an old post) in the comments:
    http://www.west-wind.com/weblog/posts/76293.aspx
  6. #6
    Hello!

    Thanks for the investigation.
    It seems you're right. There is no way to catch these events.
  7. #7
    I think in my particular case, the hiding of the mask using setTimeout we discussed earlier is a decent enough workaround. You can mark this as [CLOSED] if you want (with this limitation/caveat, I guess!)

    Thanks for your help!

Similar Threads

  1. Export grid panel data to excel
    By sumesh in forum 1.x Help
    Replies: 1
    Last Post: Sep 23, 2013, 9:07 AM
  2. Replies: 1
    Last Post: May 28, 2012, 5:17 AM
  3. Replies: 2
    Last Post: May 19, 2012, 9:09 AM
  4. Export grid panel data to excel
    By sumesh in forum 1.x Help
    Replies: 0
    Last Post: May 19, 2012, 6:01 AM
  5. [CLOSED] Export Data in Grid Panel
    By speedstepmem4 in forum 1.x Legacy Premium Help
    Replies: 1
    Last Post: Aug 29, 2011, 8:26 AM

Posting Permissions