[CLOSED] ImageCommandColumn prepareCommand fires twice

  1. #1

    [CLOSED] ImageCommandColumn prepareCommand fires twice

    Below is a scaled down version of GridPanel -> Commands -> Prepare_Commands. I placed a debugger in the javascript fn prepareCommand. There are two data rows, but the function fires four times.

    I can see that the call stack is different the second time through, but I am not sure what to make of it.

    <%@ Page Language="C#" %>
    
    <%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
    
    <script runat="server">
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!X.IsAjaxRequest)
            {
                this.Store1.DataSource = new object[]
                {
                    new object[] { "3m Co", 71.72, 0.02, 0.03, "9/1 12:00am" },
                    new object[] { "Alcoa Inc", 29.01, 0.42, 1.47, "9/1 12:00am" },
                };
                this.Store1.DataBind();
            }
        }
    </script>
    
    <!DOCTYPE html>
    
    <html>
    <head runat="server">
        <title>Prepare Commands - Ext.NET Examples</title>
        <link href="/resources/css/examples.css" rel="stylesheet" />
    
        <script>
            //in PrepareCommand we can modify command
            var prepareCommand = function (grid, command, record, row) {
                debugger;
            };
        </script>
    </head>
    <body>
        <form runat="server">
            <ext:ResourceManager ID="ResourceManager1" runat="server" />
    
            <ext:Store ID="Store1" runat="server">
                <Model>
                    <ext:Model runat="server">
                        <Fields>
                            <ext:ModelField Name="company" />
                            <ext:ModelField Name="price" Type="Float" />
                            <ext:ModelField Name="change" Type="Float" />
                            <ext:ModelField Name="pctChange" Type="Float" />
                            <ext:ModelField Name="lastChange" Type="Date" DateFormat="M/d hh:mmtt" />
                        </Fields>
                    </ext:Model>
                </Model>
            </ext:Store>
    
    
            <ext:GridPanel
                runat="server"
                StoreID="Store1"
                Title="Row commands"
                Width="800"
                Height="300">
                <ColumnModel runat="server">
                    <Columns>
                        <ext:Column runat="server" Text="Company" DataIndex="company" Flex="1" />
                        <ext:Column runat="server" Text="Price" Width="100" DataIndex="price">
                            <Renderer Format="UsMoney" />
                        </ext:Column>
                        <ext:Column runat="server" Text="Change" Width="75" DataIndex="change" />
                        <ext:Column runat="server" Text="Change" Width="75" DataIndex="pctChange" />
                        <ext:DateColumn runat="server" Text="Last Updated" Width="85" DataIndex="lastChange" />
    
                        <ext:ImageCommandColumn runat="server" Width="100" Text="Image Cmds">
                            <Commands>
                                <ext:ImageCommand Icon="Delete" CommandName="Delete" ToolTip-Text="Delete" />
                            </Commands>
                            <PrepareCommand Fn="prepareCommand" />
                            <Listeners>
                                <Command Handler="Ext.Msg.alert(command, record.data.company);" />
                            </Listeners>
                        </ext:ImageCommandColumn>
                    </Columns>
                </ColumnModel>
                <SelectionModel>
                    <ext:RowSelectionModel runat="server" Mode="Single" />
                </SelectionModel>
            </ext:GridPanel>
        </form>
    </body>
    </html>
    Last edited by Daniil; Feb 18, 2015 at 10:53 AM. Reason: [CLOSED]
  2. #2
    it's gonna be fired to each row. That's how it is supposed to work.

    Take a look on the following example: https://examples3.ext.net/#/GridPane...epare_Toolbar/
    Last edited by RCN; Feb 16, 2015 at 5:08 PM.
  3. #3
    Ok I will take a look, but there are only two rows in the grid panel and only one command per row, but it fires four times. Twice for each row.

    Fire #1 - Delete command, Row 0
    Fire #2 - Delete command, Row 1

    Fire #3 - Delete command, Row 0
    Fire #4 - Delete command, Row 1

    If you look at the stack trace during the debug you can see it is different the second time around.
  4. #4
    Cris, i replaced your prepareCommand by the following:
    <script>
        //in PrepareCommand we can modify command
        var prepareCommand = function (grid, command, record, row) {
            window.console.log(Ext.String.format("prepareCommand - {0}", new Date()));
        };
    </script>
    and prepareCommand was fired just twice, as shown bellow:

    Click image for larger version. 

Name:	pc001.png 
Views:	2 
Size:	20.1 KB 
ID:	21281

    In addition, i would like to aware you that prepareCommand is gonna be fired for each row if you sort, if you call gridInstance.getView().refresh(), and from these on.
  5. #5
    I will try it against the latest v2 trunk to see if a patch was applied. I am current running against Rev 5968 [Sept 17, 2014].
  6. #6
    Daniil,

    Anyway to find a patch for v2. I downloaded the latest revision for v2 (6340 - Feb 12, 2015) and the issue still exists. Ext.NET v3 no longer has the issue.
  7. #7
    Hello, Chris Wolcott!

    I hope you don't mind me replying while you asked for @Daniil's reponse but I think I can offer a good piece of advice here.

    Last year I went under this same issue while dealing with grid renderers. It seems the layout builder may render the cell in a two-step approach, what makes these double-calling every render event.

    For you to have control over it, you may choose to run your action either in the grid's componentLayoutCounter first or second step. It is represented by a 1 or 2 (possibly more) depending on the number of steps.

    So, if you just change your JS function to this (assuming you want to do your action in the first step), you'll be done.
            var prepareCommand = function (grid, command, record, row) {
                if (grid.componentLayoutCounter == 1) console.log("fire " + fireCnt++);
            };
    I found and discussed this issue on this thread.

    Hope this helps! Let us know if it doesn't.
    Fabrício Murta
    Developer & Support Expert
  8. #8
    No I don't mind. It is just habit that I am use to working with Daniil.

    So in the example above the code below worked fine. Basically skipping the code when grid.componentLayoutCounter == 1.

            var prepareCommand = function (grid, command, record, row) {
                if (grid.componentLayoutCounter == 1) return;
                if (command.command == 'Delete' && record.get("price") < 50) {
                    command.hidden = true;
                    command.hideMode = 'display'; //you can try 'visibility' also                 
                }            
            };
    When I added it to my code it still performed double the calls. When I checked the counter the values are 2 and 3, never 1. So if I don't want it to be called twice I could skip when 2 and process when 3. So in my case will it always be 2 and 3 or sometimes 1 and 2? I obviously want to process when it is the last time.

    Nothing breaks with it being called twice, but as a developer I like to understand why.

    So is there no patch/override for v2, since v3 is working properly. Did v3 change architecture that fixed the issue.
  9. #9
    Yes, there is a defect in ExtJS 4 / Ext.NET 2. A GridPanel is being rendered twice on initial load with a Store's AutoLoad="true" (that is by default). There was a quite comprehensive discussion in the forums regarding this problem, but I could not find.

    As a solution you could try a DeferRowRender="false" setting on the GridPanel. Though, to be honest, I am not sure it is safe.

    As an alternative solution (and stable for sure) you could set
    AutoLoad="false"
    for the Store and this for the GridPanel:
    <Listeners>
        <ViewReady Handler="this.getStore().load();" />
    </Listeners>
  10. #10
    Exactly what I needed. I used the AutoLoad="false" and added the Listener ViewReady.

    Please close the thread.

Similar Threads

  1. Replies: 2
    Last Post: Mar 09, 2013, 5:05 AM
  2. Replies: 7
    Last Post: Jan 29, 2013, 8:48 PM
  3. Replies: 0
    Last Post: Oct 26, 2011, 1:16 PM
  4. [CLOSED] grid parameter is null for prepareCommand function in 1.0.
    By vedagopal2004 in forum 1.x Legacy Premium Help
    Replies: 5
    Last Post: Feb 14, 2011, 7:47 AM
  5. Replies: 3
    Last Post: Aug 13, 2009, 3:27 PM

Posting Permissions