Announcement

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

    ListGrid enforce client only filtering

    Hi,

    I have a listgrid that gets populated with data from a RestDataSource with setShowFilterEditor=true, setFilterOnKeypress=true and setCanFilter=true for each of the list grid fields in the listgrid.

    I would like the filtering to work on the subset of data initially fetched from the datasource, effectively making it a 'client only filtering'. Is there any setting or tweak to achieve this?

    The behavior I saw in SmartGWT 2.4 is sometimes it will fire a DSRequest to the ResetDataSource with filtering criteria (server side filtering?) and sometimes it won't. And it is typically the first time when the filter editor get changed it will fire DSRequest. I couldn't figure out the pattern behind when it decides to go to server side and when it decides to apply filter only to data at client side. I also noticed setting setUseClientFiltering to false will always fire DSRequest, but setting setUseClientFiltering to true does not guarantee client side filtering every time.

    Appreciate any feedback, thanks.

    #2
    Hi,

    Any idea how to achieve this?

    Comment


      #3
      Isomorphic,

      I'm trying to achieve the same thing. Can you please explain how this can be achieved?

      I have 2 listGrid components which contain data and I want the first list selection to drive
      the second list's content. I want the second list to be filtered out based on 1st list's selection. All
      operations must be client-side.

      In the end though, when I perform an explicit save for the second's list data, I want all data
      to be saved (visible or not).

      Thanks,

      Comment


        #4
        Filtering is done client or server-side based on the Adaptive Filtering described under the ResultSet docs.

        To cause a grid to load the whole dataset and perform only client-side filtering, just set dataFetchMode:"local".

        To work with a specific subset of the data, use DataSource.getClientOnlyDataSource() to obtain a client-only DataSource representing that subset, then bind the grid to that.

        Comment


          #5
          Thanks for your reply,

          When I look at listGrid.data, I noticed the underlying data isn't a ResultSet but rather a simple Array. Because
          of this, it seems that when I perform filtering operations, the framework tries to create a ResultSet and this
          seems to be causing some issues (preliminary investigations).

          Is there a way, at creation time, to force the underlying data to be of type ResultSet instead of Array? Maybe
          that would help ...

          Thanks,

          Comment


            #6
            If you call fetchData(), grid.data will always be a ResultSet. You mist have called setData() instead with an Array, if so, use one of the previously mention approaches instead (both of which involve a call to grid.fetchData and will result in a ResultSet being created), or, if you already have the data you wan to filter available to you as an Array, you can create a ResultSet from it via resultSet.initialData and call grid.setData() with that ResultSet.

            Comment


              #7
              Thanks,

              I can't call fetchData() because I already have the data on the client. I do call setData() though using
              an Array. I'll change that setData() call to try your suggested approach, using setData() with a ResultSet,
              pre-initialized with initialData.

              Thanks for the insight,

              Comment


                #8
                Hi,

                I'm gaining some progress here with the suggested approach ... What I do now in my custom component,
                is that I wrap my data array inside a ResultSet, using the following code:

                Code:
                	//----------------------------------------------------------------------------------------------------------------------------
                	setValue : function(value)
                	{
                		if (isAn.Array(value))
                		{
                			var resultSet = ResultSet.create
                			({
                				dataSource : this.canvas.selectorLoader.dataSource,
                				allRows : value,
                				initialData : value,
                				useClientFiltering : true,
                				useClientSorting : true,
                				fetchMode : 'local'
                			});
                
                			this.canvas.setData(resultSet);
                		}
                		else
                			this.canvas.setData(value);
                	},
                With the above code, my local/client-side listGrid filtering works. Cool, but ...

                My custom component which embeds the ListGrid also has 2 methods to locally (client-side) add/remove
                data from the underlying listGrid's data.

                These methods are as follows:

                Code:
                	//----------------------------------------------------------------------------------------------------------------------------
                	removeData : function(recordsToRemove)
                	{
                		if (recordsToRemove == null || this.data == null)
                			return;
                
                		if (!isc.isAn.Array(recordsToRemove))
                			recordsToRemove = [recordsToRemove];
                
                		for (var i = 0; i < recordsToRemove.length; i++)
                			this.data.remove(recordsToRemove[i]);
                	},
                	//----------------------------------------------------------------------------------------------------------------------------
                	addData : function(newRecord)
                	{
                		if (newRecord == null || this.data == null)
                			return;
                
                		this.data.add(newRecord);
                	},
                The problem I'm facing now is that this.data doesn't seem to fully implement the List interface
                as it crashes inside both data.add() and data.remove() because data (ResultSet) doesn't implement
                the addAt() and set() methods which get called within data.add() and data.remove().

                Any idea ?

                Thanks,
                Last edited by yavery; 28 Mar 2011, 07:40.

                Comment


                  #9
                  Hi Yan,

                  ResultSet doesn't support direct cache modification because it's maintaining a partial cache of a remote dataset, and the row numbers need to be preserved.

                  If you're looking for an editable dataset, switch to the clientOnly DataSource approach. You can create such a DataSource on the fly, providing your already-loaded data as DataSource.cacheData. This way, you'll still be able to directly modify the data in the usual way.

                  Comment


                    #10
                    Thanks,

                    I'll give that approach a try.

                    Talk to you later!

                    Comment


                      #11
                      I'm doing a similar thing...

                      I have a ListGrid initially call fetchData() to populate it with a subset of data but then have filtering only be done on that subset of data on the same ListGrid.

                      I used the technique described above by creating a new client-only data source and then calling ListGrid.setDataSource(). However, doing this loses the custom fields I had set. Is there any way to save them (I'd imagine user customizations would also be lost even if I manually reset them back to the custom fields)?

                      Thanks in advance!

                      Comment


                        #12
                        You just need to call setFields() again with your custom fields after the setDataSource() call.

                        Comment


                          #13
                          I implemented your suggestion a while ago and haven't had issues but now after I call ListGrid.setFields() after setting the client-only DataSource, the ListGrid doesn't appear and I get the attached dialog.

                          I've tried calling setFields() before and after fetchData() with no luck. I also tried calling ListGrid.setCanSort(true) before and after the setFields() with no luck.

                          Any clues on how to debug this? Thanks!
                          Attached Files

                          Comment


                            #14
                            What this suggests is that the grid is rebuilding it's header (creating new ImgButton components) at a time when it's fields are invalid or have somehow shortened. It's not clear how you could get into this state, but it might involve multiple calls to setFields() on a grid that isn't drawn, or some kind of internal mucking with components, such as forcing redraw()s or layout reflow()s.

                            Are you able to isolate this to a test case we can run to take a look?

                            Comment


                              #15
                              Thanks for the hint.

                              The problem was before we were fetching, we were resetting the data source of the ListGrid back to the original so that we could get new data then calling fetchData. After that, in a callback, we would set the data source to a client-only only copy of the data source. This probably caused the invalid state you mentioned.

                              To fix it, instead of calling a fetchData on the ListGrid, I directly called it on the DataSource instance. Then in the callback, I used the data from the DSResponse to set the cache data in the client-only data source. That way, I think the ListGrid wouldn't have to redraw because we only set its DataSource
                              and fields once.

                              Again, thanks for your help!

                              Comment

                              Working...
                              X