Announcement

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

    Problem with 'flicker' on sorted ListGrid

    I am having a problem with a double fetch on a ListGrid when I setData with a ResultSet. This is a follow-up question to this thread. I'm using the following SC_SNAPSHOT-2011-01-04/PowerEdition Deployment (built 2011-01-04), Firefox 3.6.15, Windows 7.

    Here is a small example program to demonstrate what I am seeing:
    Code:
    package com.smartgwt.sample.client;
    
    import com.smartgwt.client.data.DSCallback;
    import com.smartgwt.client.data.DSRequest;
    import com.smartgwt.client.data.DSResponse;
    import com.smartgwt.client.data.DataSource;
    import com.smartgwt.client.data.ResultSet;
    import com.smartgwt.client.types.FetchMode;
    import com.smartgwt.client.types.TextMatchStyle;
    import com.smartgwt.client.widgets.IButton;
    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.layout.VLayout;
    
    public class RefreshGridTest 
    	extends VLayout
    {
    	private ListGrid grid;
    	private static final int REFRESH_ROW_OFFSET = 15;
    	
    	public RefreshGridTest()
    	{
    		setMargin(10);
    		setWidth(400);
    		setHeight(500);
    		setMembersMargin(5);
    		
    		grid = new ListGrid();
    		grid.setDataSource(DataSource.get("PING"));
    		grid.setWidth100();
    		grid.setHeight100();
    		grid.setShowFilterEditor(true);
    		grid.setFetchDelay(500);
    		grid.setFilterOnKeypress(true);
    		grid.setAutoFetchData(true);
    				
    		addMember(grid);
    		
    		final IButton button = new IButton("refresh");
    		button.addClickHandler(new ClickHandler() {
    			@Override
    			public void onClick(ClickEvent event) {
    				refresh();
    			}
    		});
    
    		addMember(button);
    	}
    
    	private void refresh()
    	{
    		final Integer row[] = grid.getVisibleRows();
    		
    		final DSRequest request = new DSRequest();
    		request.setStartRow(Math.max(0, row[0] - REFRESH_ROW_OFFSET));
    		request.setEndRow(row[1] + REFRESH_ROW_OFFSET);
    		request.setTextMatchStyle(TextMatchStyle.SUBSTRING);
    		request.setSortBy(grid.getSort());
    
    		final DataSource ds = grid.getDataSource();
    		ds.setShowPrompt(false);
    		ds.fetchData(grid.getFilterEditorCriteria(), new DSCallback() {
    
    			@Override
    			public void execute(DSResponse response, Object rawData, DSRequest request)
    			{
    				final ResultSet resultset = new ResultSet();
    				resultset.setDataSource(ds);
    				resultset.setFetchMode(FetchMode.PAGED);
    				resultset.setInitialLength(response.getTotalRows());
    				resultset.setInitialData(response.getData());
    				
    				grid.setData(resultset);
    				
    			}
    		}, request);
    	}
    }
    Here is the accompanying ds.xml file:
    Code:
    <DataSource schema="PING" dbName="Oracle" tableName="PING" ID="PING" serverType="sql" >
    	<fields>
    		<field sequenceName="PING_SEQ" primaryKey="true" name="id" type="sequence" hidden="true"></field>
    		<field name="name" length="51" type="text">
    			<validators>
    				<validator type="isUnique" requiresServer="true" />
    			</validators>
    		</field>
    		<field name="other" length="21" type="text">
    		</field>
    	</fields>
    </DataSource>
    When the "other" column is filtered and I press the refresh button, only one DSRequest is made and the ListGrid will updates without a 'flicker'.

    However, if I press the refresh button with the "other" column sorted, two DSRequests are made and the ListGrid updates with a 'flicker'.

    The double fetch seems to be related to when the totalRows is greater than the number of rows returned in the DSResponse and the column is sorted. Is there something I can do differently to avoid the 'flicker' on sorted columns?

    #2
    You retrieved sorted data, but the ResultSet won't know it's sorted unless you call sortByProperty() on it.

    Comment


      #3
      That did not work. This is what I added:
      Code:
      resultset.sortByProperty("other", true);
      grid.setData(resultset);
      Clicking the refresh button still causes a double-fetch. I also tried to set the sort, which I'd prefer since the "name" column could be sorted too, before the setData.
      Code:
      resultset.setSort(request.getSortBy()); 
      grid.setData(resultset);
      But that also caused a double-fetch. Am I misunderstanding the change I was to make?

      Comment


        #4
        Just a sanity check: in the RPC tab it shows what component initiated the fetch - what do you see for the two fetches?

        Comment


          #5
          The component is blank for both fetches.

          Here is the DSRequest for 1st fetch (triggered by the button click):
          Code:
          {
              "dataSource":"PING", 
              "operationType":"fetch", 
              "data":{
              }, 
              "startRow":0, 
              "endRow":33, 
              "sortBy":[
                  "other"
              ], 
              "textMatchStyle":"substring", 
              "showPrompt":false, 
              "oldValues":{
              }, 
              "requestId":"PING$6272"
          }
          Here is the DSRequest for the 2nd fetch:
          Code:
          {
              "dataSource":"PING", 
              "operationType":"fetch", 
              "data":{
              }, 
              "startRow":0, 
              "endRow":75, 
              "sortBy":[
                  "other"
              ], 
              "resultSet":[ResultSet ID:isc_ResultSet_1 (created by: undefined)], 
              "callback":{
                  "caller":[ResultSet ID:isc_ResultSet_1 (created by: undefined)], 
                  "methodName":"fetchRemoteDataReply"
              }, 
              "willHandleError":true, 
              "showPrompt":false, 
              "oldValues":{
              }, 
              "clientContext":{
                  "requestIndex":1
              }, 
              "requestId":"PING$6273"
          }
          Attached is a low quality screen grab of the SC Developer Console.
          Attached Files

          Comment


            #6
            Ah - I see the ResultSet is missing an API to set initial sort specifications as part of creation.

            We've now added this - as of the next nightly build you should see ResultSet.setInitialSort() which you can specify along with initialLength and initialData when creating the resultSet.

            Comment


              #7
              Thanks. That took care of it.

              Comment


                #8
                Hi, I'm doing a similar thing - but before I commit to using nightly code can you tell me if your scroll bar remains in place after a refresh or does it jump to the top?

                Thanks

                Comment


                  #9
                  If you're curious; my current approach is to get a set of IDs from the server that represent updated rows since the last refresh. I then update the appropriate rows or add the new ones.

                  While my approach works I've realised that the overhead of constantly updating the view is minimal especially with a large data set where most of the deltas are off the screen.

                  Comment


                    #10
                    Originally posted by scarlethue
                    Hi, I'm doing a similar thing - but before I commit to using nightly code can you tell me if your scroll bar remains in place after a refresh or does it jump to the top?
                    The scroll bar remains in place.

                    Comment

                    Working...
                    X