Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    ListGrid DataArrivedHandler / ResultSet size/totalRows issue after delete/update

    Hi Isomorphic,

    my main layout is a SectionStack filled with grouped ListGrid in it's sections. I create the ListGrids and load data lazy on SectionStackSection-open.
    Now the users are asking for a total row count in each ListGrid, which I'd like to display in the SectionStackSection-title after the ListGrid loads.

    This works fine with a DataArrivedHandler in the ListGrid after DB-fetches and after filtering (local as well as for a DB-fetch with criteria).

    It does not work for updates (change the lifeSpan in the ListGrid in the attached sample). The DataArrivedHandler is hit, but ListGrid.getResultSet().getLength() does return the same value as before.
    Like for local filtering, I'd expect the value to be correct (so +1, if the ResultSet got bigger or -1 if the update removed the row from the ResultSet.
    Also, for a remove (delete a record via the delete button at the end of the row the attached sample), DataArrivedHandler is not hit.

    Can you tell me if one or both of these behaviors are bugs, and if not, how to best solve this usecase?

    BuiltInDS.java (v10.1p_2017-10-05):
    Code:
    package com.smartgwt.sample.client;
    
    import com.google.gwt.core.client.EntryPoint;
    import com.smartgwt.client.Version;
    import com.smartgwt.client.core.KeyIdentifier;
    import com.smartgwt.client.data.AdvancedCriteria;
    import com.smartgwt.client.data.Criterion;
    import com.smartgwt.client.data.DataSource;
    import com.smartgwt.client.types.OperatorId;
    import com.smartgwt.client.util.Page;
    import com.smartgwt.client.util.PageKeyHandler;
    import com.smartgwt.client.util.SC;
    import com.smartgwt.client.widgets.IButton;
    import com.smartgwt.client.widgets.Window;
    import com.smartgwt.client.widgets.events.ClickEvent;
    import com.smartgwt.client.widgets.events.ClickHandler;
    import com.smartgwt.client.widgets.grid.ListGrid;
    import com.smartgwt.client.widgets.grid.ListGridField;
    import com.smartgwt.client.widgets.grid.events.DataArrivedEvent;
    import com.smartgwt.client.widgets.grid.events.DataArrivedHandler;
    import com.smartgwt.client.widgets.layout.VLayout;
    
    public class BuiltInDS extends VLayout implements EntryPoint {
        public void onModuleLoad() {
            KeyIdentifier debugKey = new KeyIdentifier();
            debugKey.setCtrlKey(true);
            debugKey.setKeyName("D");
    
            Page.registerKey(debugKey, new PageKeyHandler() {
                public void execute(String keyName) {
                    SC.showConsole();
                }
            });
            setWidth100();
            setHeight100();
    
            final IButton recreateBtn = new IButton("Recreate");
            recreateBtn.addClickHandler(new ClickHandler() {
                @Override
                public void onClick(ClickEvent event) {
                    new MyWindow().show();
                }
            });
            addMember(recreateBtn);
            new MyWindow().show();
            draw();
        }
    
        private class MyWindow extends Window {
            public MyWindow() {
                setBackgroundColor("#F5F5F5");
                setBodyColor("#F5F5F5");
                setCanFocus(true);
                setWidth(800);
                setHeight(1000);
                setMembersMargin(0);
                setModalMaskOpacity(70);
                setTitle(" (" + Version.getVersion() + "/" + Version.getSCVersionNumber() + ")");
                setTitle("ListGrid DataArrivedHandler / ResultSet size/totalRows issue after delete/update" + getTitle());
                setShowMinimizeButton(false);
                setIsModal(true);
                setShowModalMask(true);
                centerInPage();
    
                ListGrid animalsLG1 = new AnimalsLG("animalsLG1");
                ListGrid animalsLG2 = new AnimalsLG("animalsLG2");
                VLayout messagesVLayout = new VLayout(10);
                messagesVLayout.setWidth100();
                messagesVLayout.addMembers(animalsLG1, animalsLG2);
                addItem(messagesVLayout);
    
                animalsLG1.fetchData(new AdvancedCriteria(new Criterion("lifeSpan", OperatorId.LESS_OR_EQUAL, 20)));
                animalsLG2.fetchData(new AdvancedCriteria(new Criterion("lifeSpan", OperatorId.GREATER_THAN, 20)));
            }
        }
    
        private class AnimalsLG extends ListGrid {
            public AnimalsLG(final String lgName) {
                super(DataSource.get("animals"));
                setCanEdit(true);
                setCanRemoveRecords(true);
                setAutoFetchData(false);
                setAllowFilterExpressions(true);
                setShowFilterEditor(true);
                setWidth100();
    
                ListGridField commonNameLGF = new ListGridField("commonName");
                commonNameLGF.setCanFilter(false);
                ListGridField scientificNameLGF = new ListGridField("scientificName");
                scientificNameLGF.setCanFilter(false);
                ListGridField lifeSpanLGF = new ListGridField("lifeSpan");
                ListGridField statusLGF = new ListGridField("status");
                statusLGF.setCanFilter(false);
                ListGridField dietLGF = new ListGridField("diet");
                dietLGF.setCanFilter(false);
                setFields(commonNameLGF, scientificNameLGF, lifeSpanLGF, statusLGF, dietLGF);
                setSortField("commonName");
    
                addDataArrivedHandler(new DataArrivedHandler() {
                    @Override
                    public void onDataArrived(DataArrivedEvent event) {
                        int i = AnimalsLG.this.getResultSet().getLength();
                        SC.logWarn(lgName + "-Result length: " + i);
                    }
                });
            }
        }
    }
    Thank you & Best regards
    Blama

    #2
    Does grid.getTotalRows() return the right value?

    Comment


      #3
      Hi Isomorphic,

      thanks for the fast answer. Yes and no - in a grouped LG this also counts grouping rows. Also, I managed to recreate a warning I see in my application all the time, that I can't explain.

      Please see this revised testcase:
      Code:
      package com.smartgwt.sample.client;
      
      import com.google.gwt.core.client.EntryPoint;
      import com.smartgwt.client.Version;
      import com.smartgwt.client.core.KeyIdentifier;
      import com.smartgwt.client.data.AdvancedCriteria;
      import com.smartgwt.client.data.Criterion;
      import com.smartgwt.client.data.DataSource;
      import com.smartgwt.client.types.OperatorId;
      import com.smartgwt.client.util.Page;
      import com.smartgwt.client.util.PageKeyHandler;
      import com.smartgwt.client.util.SC;
      import com.smartgwt.client.widgets.IButton;
      import com.smartgwt.client.widgets.Window;
      import com.smartgwt.client.widgets.events.ClickEvent;
      import com.smartgwt.client.widgets.events.ClickHandler;
      import com.smartgwt.client.widgets.grid.ListGrid;
      import com.smartgwt.client.widgets.grid.ListGridField;
      import com.smartgwt.client.widgets.grid.events.DataArrivedEvent;
      import com.smartgwt.client.widgets.grid.events.DataArrivedHandler;
      import com.smartgwt.client.widgets.layout.VLayout;
      
      public class BuiltInDS extends VLayout implements EntryPoint {
          public void onModuleLoad() {
              KeyIdentifier debugKey = new KeyIdentifier();
              debugKey.setCtrlKey(true);
              debugKey.setKeyName("D");
      
              Page.registerKey(debugKey, new PageKeyHandler() {
                  public void execute(String keyName) {
                      SC.showConsole();
                  }
              });
              setWidth100();
              setHeight100();
      
              final IButton recreateBtn = new IButton("Recreate");
              recreateBtn.addClickHandler(new ClickHandler() {
                  @Override
                  public void onClick(ClickEvent event) {
                      new MyWindow().show();
                  }
              });
              addMember(recreateBtn);
              new MyWindow().show();
              draw();
          }
      
          private class MyWindow extends Window {
              public MyWindow() {
                  setBackgroundColor("#F5F5F5");
                  setBodyColor("#F5F5F5");
                  setCanFocus(true);
                  setWidth(800);
                  setHeight(1000);
                  setMembersMargin(0);
                  setModalMaskOpacity(70);
                  setTitle(" (" + Version.getVersion() + "/" + Version.getSCVersionNumber() + ")");
                  setTitle("ListGrid DataArrivedHandler / ResultSet size/totalRows issue after delete/update" + getTitle());
                  setShowMinimizeButton(false);
                  setIsModal(true);
                  setShowModalMask(true);
                  centerInPage();
      
                  ListGrid animalsLG1 = new AnimalsLG("animalsLG1");
                  ListGrid animalsLG2 = new AnimalsLG("animalsLG2");
                  VLayout messagesVLayout = new VLayout(10);
                  messagesVLayout.setWidth100();
                  messagesVLayout.addMembers(animalsLG1, animalsLG2);
                  addItem(messagesVLayout);
      
                  animalsLG1.fetchData(new AdvancedCriteria(new Criterion("lifeSpan", OperatorId.LESS_OR_EQUAL, 20)));
                  animalsLG2.fetchData(new AdvancedCriteria(new Criterion("lifeSpan", OperatorId.GREATER_THAN, 20)));
              }
          }
      
          private class AnimalsLG extends ListGrid {
              public AnimalsLG(final String lgName) {
                  super(DataSource.get("animals"));
                  setCanEdit(true);
                  setCanRemoveRecords(true);
                  setAutoFetchData(false);
                  setAllowFilterExpressions(true);
                  setShowFilterEditor(true);
                  setShowRowNumbers(true);
                  setWidth100();
      
                  ListGridField commonNameLGF = new ListGridField("commonName");
                  commonNameLGF.setCanFilter(false);
                  ListGridField scientificNameLGF = new ListGridField("scientificName");
                  scientificNameLGF.setCanFilter(false);
                  ListGridField lifeSpanLGF = new ListGridField("lifeSpan");
                  ListGridField statusLGF = new ListGridField("status");
                  statusLGF.setCanFilter(false);
                  ListGridField dietLGF = new ListGridField("diet");
                  dietLGF.setCanFilter(false);
                  setFields(commonNameLGF, scientificNameLGF, lifeSpanLGF, statusLGF, dietLGF);
                  setSortField("commonName");
      
                  addDataArrivedHandler(new DataArrivedHandler() {
                      @Override
                      public void onDataArrived(DataArrivedEvent event) {
                          int i;
                          if (!AnimalsLG.this.isGrouped())
                              i = AnimalsLG.this.getResultSet().getLength();
                          else
                              i = AnimalsLG.this.getOriginalResultSet().getLength();
      
                          int i2 = AnimalsLG.this.getTotalRows();
      
                          SC.logWarn(lgName + "-Result length: getResultSet().getLength(): " + i + " / getTotalRows(): " + i2);
                      }
                  });
              }
          }
      }
      Issues:
      • DataArrivedHandler is not called for both ListGrids after an edit/update, only for the 1st one. Actually I did not find a pattern here. If you play around with the sample,
        • edit lifeSpan-values so that they stay in the same LG
        • edit lifeSpan-values so that they move to the other LG
        • filter values
      you will notice that the result of which handler is hit is not really predictable.
      • Deletes sometimes trigger the handler, sometimes not.
      • Sometimes, when rows switch ListGrids after an edit, I see this log message:
        14:31:12.053:XRP0:WARN:ResultSet:isc_ResultSet_4 (dataSource: animals, created by: isc_BuiltInDS_AnimalsLG_4):getRange(3, 4): start beyond end of rows, returning empty list
        It seems to always be related to the 2nd ListGrid.
      I tested with v10.1p_2017-10-05 in FF26 dev mode, but know the issues from my Application as well.
      In v10.1p_2017-08-20 compiled (with GC61 and possibly others) I saw the last warning often and could not figure out why (and did not investigate, as well).
      In v11.1p_2017-10-11 compiled (with GC61 and possibly others) I have the issue with the not hit DataArrivedHandler.

      Best regards
      Blama

      Comment


        #4
        The dataArrived event is only triggered under certain circumstances - data returned by a fetch from the server or cache invalidation, and filtering operations. You should be using the dataChanged event instead, though you had a good excuse not to since we've just exposed it now, in SGWT 5.1p/SC 10.1p and newer branches. (We also suppressed the warning you mentioned, though it was causing no harm.)

        The changes will be in the nightly builds dated 2017-10-27 and beyond.

        Comment


          #5
          Hi Isomorphic,

          generally speaking, this is working as expected using v10.1p_2017-11-01. There is one issue left with grouped ListGrids, though.

          Please have a look at this revised testcase:
          Code:
          package com.smartgwt.sample.client;
          
          import com.google.gwt.core.client.EntryPoint;
          import com.smartgwt.client.Version;
          import com.smartgwt.client.core.KeyIdentifier;
          import com.smartgwt.client.data.AdvancedCriteria;
          import com.smartgwt.client.data.Criterion;
          import com.smartgwt.client.data.DataSource;
          import com.smartgwt.client.data.SortSpecifier;
          import com.smartgwt.client.types.OperatorId;
          import com.smartgwt.client.types.SortDirection;
          import com.smartgwt.client.util.Page;
          import com.smartgwt.client.util.PageKeyHandler;
          import com.smartgwt.client.util.SC;
          import com.smartgwt.client.widgets.IButton;
          import com.smartgwt.client.widgets.Window;
          import com.smartgwt.client.widgets.events.ClickEvent;
          import com.smartgwt.client.widgets.events.ClickHandler;
          import com.smartgwt.client.widgets.grid.ListGrid;
          import com.smartgwt.client.widgets.grid.ListGridField;
          import com.smartgwt.client.widgets.grid.events.DataChangedEvent;
          import com.smartgwt.client.widgets.grid.events.DataChangedHandler;
          import com.smartgwt.client.widgets.layout.VLayout;
          
          public class BuiltInDS extends VLayout implements EntryPoint {
              public void onModuleLoad() {
                  KeyIdentifier debugKey = new KeyIdentifier();
                  debugKey.setCtrlKey(true);
                  debugKey.setKeyName("D");
          
                  Page.registerKey(debugKey, new PageKeyHandler() {
                      public void execute(String keyName) {
                          SC.showConsole();
                      }
                  });
                  setWidth100();
                  setHeight100();
          
                  final IButton recreateBtn = new IButton("Recreate");
                  recreateBtn.addClickHandler(new ClickHandler() {
                      @Override
                      public void onClick(ClickEvent event) {
                          new MyWindow().show();
                      }
                  });
                  addMember(recreateBtn);
                  new MyWindow().show();
                  draw();
              }
          
              private class MyWindow extends Window {
                  public MyWindow() {
                      setBackgroundColor("#F5F5F5");
                      setBodyColor("#F5F5F5");
                      setCanFocus(true);
                      setWidth(800);
                      setHeight(1000);
                      setMembersMargin(0);
                      setModalMaskOpacity(70);
                      setTitle(" (" + Version.getVersion() + "/" + Version.getSCVersionNumber() + ")");
                      setTitle("ListGrid DataArrivedHandler / ResultSet size/totalRows issue after delete/update" + getTitle());
                      setShowMinimizeButton(false);
                      setIsModal(true);
                      setShowModalMask(true);
                      centerInPage();
          
                      ListGrid animalsLG1 = new AnimalsLG("animalsLG1");
                      ListGrid animalsLG2 = new AnimalsLG("animalsLG2");
                      VLayout messagesVLayout = new VLayout(10);
                      messagesVLayout.setWidth100();
                      addItem(messagesVLayout);
          
                      animalsLG1.fetchData(new AdvancedCriteria(new Criterion("lifeSpan", OperatorId.LESS_OR_EQUAL, 20)));
                      animalsLG2.fetchData(new AdvancedCriteria(new Criterion("lifeSpan", OperatorId.GREATER_THAN, 20)));
                      messagesVLayout.addMembers(animalsLG1, animalsLG2);
                  }
              }
          
              private class AnimalsLG extends ListGrid {
                  public AnimalsLG(final String lgName) {
                      super(DataSource.get("animals"));
                      setGroupSortDirection(SortDirection.ASCENDING);
                      setGroupByField("status");
                      setAutoFetchData(false);
                      setAllowFilterExpressions(true);
                      setShowFilterEditor(true);
                      setWidth100();
          
                      ListGridField commonNameLGF = new ListGridField("commonName");
                      commonNameLGF.setCanFilter(false);
                      ListGridField scientificNameLGF = new ListGridField("scientificName");
                      scientificNameLGF.setCanFilter(false);
                      ListGridField lifeSpanLGF = new ListGridField("lifeSpan");
                      ListGridField statusLGF = new ListGridField("status");
                      statusLGF.setCanFilter(false);
                      ListGridField dietLGF = new ListGridField("diet");
                      dietLGF.setCanFilter(false);
                      setFields(commonNameLGF, scientificNameLGF, lifeSpanLGF, statusLGF, dietLGF);
                      setSort(new SortSpecifier[] { new SortSpecifier("commonName", SortDirection.ASCENDING) });
          
                      addDataChangedHandler(new DataChangedHandler() {
                          @Override
                          public void onDataChanged(DataChangedEvent event) {
          [B]int numOfRecords = -1;[/B]
                              int totalRows = AnimalsLG.this.getTotalRows();
                              if (AnimalsLG.this.isGrouped() && AnimalsLG.this.getOriginalResultSet() != null
                                      && AnimalsLG.this.getOriginalResultSet().lengthIsKnown())
                                  numOfRecords = AnimalsLG.this.getOriginalResultSet().getLength();
                              // If ungrouped
                              if (!AnimalsLG.this.isGrouped() && AnimalsLG.this.getResultSet() != null && AnimalsLG.this.getResultSet().lengthIsKnown())
                                  numOfRecords = AnimalsLG.this.getResultSet().getLength();
          
                              SC.logWarn(lgName + "-Result length: getResultSet().getLength(): " + numOfRecords + " / getTotalRows(): " + totalRows);
                          }
                      });
                  }
              }
          }
          On start, I get these error messages:
          Code:
          [DEBUG] [builtinds] - Linking module 'builtinds'
          [B][ERROR] [builtinds] - 13:56:12.487:WARN:Log:animalsLG1-Result length: getResultSet().getLength(): -1 / getTotalRows(): 1000
          [ERROR] [builtinds] - 13:56:12.738:WARN:Log:animalsLG2-Result length: getResultSet().getLength(): -1 / getTotalRows(): 1000[/B]
          [INFO] [builtinds] - Module builtinds has been loaded
          [ERROR] [builtinds] - 13:56:13.895:XRP7:WARN:Log:animalsLG2-Result length: getResultSet().getLength(): 13 / getTotalRows(): 13
          [ERROR] [builtinds] - 13:56:13.932:XRP8:WARN:Log:animalsLG1-Result length: getResultSet().getLength(): 15 / getTotalRows(): 15
          As you can see, the handler is called twice, once with bogus data. I'd expect it to be called once. This is not nice, but perhaps just the way it is.

          In my application with more complex ListGrid and ViewState management, it is getting called three times, where the first time (that's the extra call, the two others you see above follow directly afterwards) a warning complains about the ListGrid not being DataBound and suggests using getRecordList() instead of getResultSet()/getOriginalResultSet(). Unfortunately I was not able to reproduce this in a testcase, yet.

          Do you have an idea what might be causing these extra calls?

          Thank you & Best regards
          Blama

          Comment


            #6
            The data is not "bogus" in the call you mention - it's just that the length of the ResultSet's data isn't known yet. That's why you're getting the "unknown length" value of 1000 when calling ListGrid.getTotalRows(). You actually already have some calls to ResultSet.lengthIsKnown() in your repro code above, but your code still outputs values even if that method returns false.
            Last edited by Isomorphic; 15 Nov 2017, 03:15.

            Comment

            Working...
            X