Announcement

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

    ListGrid: selecting/ scrolling to not loaded records

    Let's suppose I have a ListGrid, which shows some records from a DS.
    At first, only that is shown (a few screens forward) are loaded; most of the data is loaded only on demand.

    Now let's suppose I need to select a record (or a set of records) by the primary keys, but it's possible that it is not even loaded yet. How do I do that?

    The desired behavior is that when selecting a record, it should be loaded, marked (visually) as selected, and the grid should scroll to it. Likewise, when selecting a set of records, load all of them (so that getSelection() can return them), and scroll to the first.

    If the wanted record is loaded, I can say something like
    Code:
    list.selectRecord(list.getResultSet().findByKey(id));
    , but then this won't work with not yet loaded records.

    How do I do this?
    Last edited by csillag; 7 Mar 2010, 15:33.

    #2
    You need to make a call to the server to discover the index of the record within the overall dataset, then scroll the ListGrid to the row coordinate. This will cause an automatic fetch which will include the record you want - the next time DataArrived fires, use findByKey() and selectRecord() to select it.

    Comment


      #3
      Originally posted by Isomorphic
      You need to make a call to the server to discover the index of the record within the overall dataset, then scroll the ListGrid to the row coordinate.
      1. How do I find out the coordinate of the record on the server side?

      2. When I need to select a set of records, it's possible that they are dispersed all over the dataset. If I scroll to the coordinate of the first record, others might stay hidden, so auto-fetch will not get them. How can I solve this? (Without loading all the data, of course.)
      Last edited by csillag; 8 Mar 2010, 13:24.

      Comment


        #4
        Originally posted by csillag
        2. When I need to select a set of records, it's possible that they are dispersed all over the dataset. If I scroll to the coordinate of the first record, others might stay hidden, so auto-fetch will not get them. How can I solve this? (Without loading all the data, of course.)
        Would it make sense to
        - make a call to the server side to determine all the coordinates, and
        - on the underlying ResultSet, manually calling getRange() for all the relevant regions?

        Would this make the wanted records available in the ListGrid?

        Or is there a better way do to this?

        Comment


          #5
          Yes, that would be a way to load a bunch of separate ranges at once. It seems a little strange to do so since you can only scroll to one position at any given time (hence you might as well defer the other fetches), but maybe you have an unusual use case.

          Be sure to use RPCManager.startQueuing() and sendQueue() around the getRange() calls to make it into a single HTTP fetch. Also, be sure to setFetchDelay(0) before initiating those calls, then re-set it to it's original value. Otherwise a series of getRange() calls may result in only the range specified by the final call actually being fetched.

          Comment


            #6
            Originally posted by Isomorphic
            It seems a little strange to do so since you can only scroll to one position at any given time (hence you might as well defer the other fetches), but maybe you have an unusual use case.
            I have two reasons not to defer the other fetches:

            1. I need to execute the selection request at that point, so that when the user scrolls down, and loads the unloaded ranges, the records referenced in this request will be selected.

            2. I need the contents of the records to be available for ListGrid.getSelection(), independently of the fact that they are displayed or not.

            Does that make sense?

            UPDATE: I would still like to know how to find out the coordinate of a record on the server side.
            Last edited by csillag; 8 Mar 2010, 18:22.

            Comment


              #7
              Sure, although you could also grab just the set of records in question via DataSource.fetchData(), use those for whatever purpose getSelection() would have been used, and select rows as they are loaded via listening for DataArrived.

              As far as finding the row index, it could possibly be done with some fancy SQL, but the simple approach of just selecting all matching records and searching the result array also works.

              Comment


                #8
                Originally posted by Isomorphic
                As far as finding the row index, it could possibly be done with some fancy SQL, but the simple approach of just selecting all matching records and searching the result array also works.
                To select all the matching records on the server side, I need to run a search with the same criteria that is currently used at the client side, right?

                I can get the criteria with ListGrid.getCriteria(), but how do I transfer this to the server? This Criteria class does not exist on the server side, and it's not even serializable.

                How do I use this on the server side?

                UPDATE: about the background: if it's not obvious, I use the built-in SQL backend for data storage, so most of the client-server communication happens automatically. For the few things I need to do on the server manually (like the current operation) I use custom GWT-RPC calls. (Note that I am not talking about the DataSource operations here.) I am aware that this is not as efficient as your own solution, but since the data communication is happening on an other channel, I have not cared until so far. Is this the root of the problem?

                UPDATE2: If I implemented this server call as a special DS operation, then I guess I could transfer the criteria from the client to the server side automatically. But defining custom DMI operations would require modifications in all the involved DataSource definitions, which is not exactly what I want.
                Last edited by csillag; 9 Mar 2010, 10:10.

                Comment


                  #9
                  this problem is killing me

                  Comment


                    #10
                    Yes, it is a stupendously bad idea to create GWT-RPC services, for the reason you pointed out (no automatic serialization of criteria et al), and also because they aren't provided with the rich server-side context that SmartGWT provides (the DataSource, spring services, etc) and also because it's just a lot of extra code, and also, critically, because they can't participate in queuing (see the "Transactions" examples folder).

                    Just assemble a DSRequest that matches the criteria/sort/etc of the grid in question, then add in the primaryKey values of the records you need, and pass the DSRequest to DataSource.fetchData(). Server-side you can remove the primaryKey values from the DSRequest and allow it to execute, then find the records in the resulting dsResponse.data.

                    Your return data can be the usual List of Maps, where each Map has the primaryKey of the record and it's index in the dataset.

                    You can add this logic as a custom SQLDataSource subclass if you need it for all DataSources.

                    Comment


                      #11
                      As I have already pointed out, I was _not_ using GWT-RPC calls for DataSource-related data transfers, therefore, queuing was no concern. (The same goes for serializing criteria.) I was using it to access/control other features of the server application. (Check server app status, start various server processes, get list of available data sources, stuff like that.) These operations are typically not executed very often.

                      Is it wrong to use GWT-RPC even for these tasks?

                      This current problem is somewhat different, so as you say, I will implement this as a DSRequest. Thank you for explaining.

                      A few more simple questions:

                      1. Besides criteria and sort, what else should I configure on the DSRequest, so that the result will be identical with that of the ListGrid?

                      2. On the DSRequest I build on the client site, how do I add in the primaryKey values? (Should I add a new, fake criteria for that?)

                      3. How should I flag the DSRequest, so that my server-side logic can recognize that this request needs to be handled differently? (Operation id? Fake critieria?)

                      4. Exactly where should I introduce my customized SQLDataSource subclass, to override the default behavior? (Specify ServerConstructor in the DS XML?)

                      Thank you for your help!
                      Last edited by csillag; 9 Mar 2010, 14:32.

                      Comment


                        #12
                        It's wrong to use GWT-RPC in the sense that it's extra work, one or more of those operations is likely to require queuing at some point, and you further erode the value of SmartGWT's diagnostic tools and other common services (you cannot, eg, see all calls in the RPC tab anymore, or see their relative order of execution/completion, or put all your error handling and logging in one place, and so on).

                        1. Possibly textMatchStyle - see filterData

                        2. Just add them as part of the criteria argument to fetchData

                        3. operationId

                        4. See the Custom DataSource sample

                        Comment


                          #13
                          OK, so where can I find an example for implementing generic (ie. non-datasource related) RPC calls with SmartGWT, without GWT-RPC?

                          (Besides the javadoc for RPCManager)

                          Comment


                            #14
                            When I have the record numbers I want, I should check whether they are already loaded. The docs for ResultSet says this:

                            "Calling getRange for records that have not yet loaded will trigger an asynchronous fetch. The returned data will contain the marker value Array.LOADING as a placeholder for records being fetched. If any rows needed to be fetched, dataArrived() will fire when they arrive. "

                            So I guess I should check for this Array.LOADING marker on my ResultSet, but I can not find out how. I already understand that Array.LOADING is a JS object; is there a Java wrapper for it? Or how should I check for it?

                            Comment


                              #15
                              Originally posted by csillag
                              So I guess I should check for this Array.LOADING marker on my ResultSet, but I can not find out how. I already understand that Array.LOADING is a JS object; is there a Java wrapper for it? Or how should I check for it?
                              Actually, it's really easy. Regardless of any marker, not yet loaded records are empty (ie. getAttributes() returns an empty array).

                              Comment

                              Working...
                              X