Announcement

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

    How to get records from a datasource with client side code?

    This is a sub question I ask before, but I reformulate it to be more specific!

    I want to get the records sent by a datasource with client side code.

    The datasource work and return 1 row.

    I tried to interact with the datasource directly, but I got an
    index out of bound on userDS.getCacheData (it is empty):

    DataSource userDS = DataSource.get("user");
    userDS.setCacheAllData(true);
    userDS.fetchData();
    Record r = userDS.getCacheData()[0];
    User user = new User();
    user.setName(r.getAttributeAsString("Name"));
    user.setRead(r.getAttributeAsBoolean("Read"));
    user.setWrite(r.getAttributeAsBoolean("Write"));
    user.setAdmin(r.getAttributeAsBoolean("Admin"));

    So I tried to get it through a ListGrid, but got only null value.

    DataSource userDS = DataSource.get("user");
    ListGrid grid = new ListGrid();
    grid.setDataSource(userDS);
    grid.fetchData();
    ListGridRecord r = grid.getRecord(0);
    User user = new User();
    user.setName(r.getAttributeAsString("Name"));
    user.setRead(r.getAttributeAsBoolean("Read"));
    user.setWrite(r.getAttributeAsBoolean("Write"));
    user.setAdmin(r.getAttributeAsBoolean("Admin"));

    What is the correct way to do this?

    Thank in advance for your help!

    #2
    Dear jgauthier,

    I had the same problem and I solved it not really elegantly, but I'll show my solution anyway.

    I read here and there that getting records directly from datasource is in the TODO list of the development team.

    Th solution I used is extending the datasource class and putting inside it a datasource linkable element whose record could be picked (I user TreeGrid)

    Code:
    public class DUMListDataSource extends RestDataSource {
    
        private TreeGrid tree = null;
        private Record[] records = null;
    
        public void build(){
            if ( tree == null ){
                tree = new TreeGrid();
                tree.setDataSource( this );
                tree.setDataFetchMode( FetchMode.LOCAL );
                tree.fetchData();
            }
        }
    
        public Record getRecordByDumID( String dumID ){
            if ( dumID == null )
                return null;
    
            if ( dumID.equals( "" ) ){
                return null;
            }
    
            if ( tree == null ){
                tree = new TreeGrid();
                tree.setDataSource( this );
                tree.setDataFetchMode( FetchMode.LOCAL );
            }
    
            if( records == null ){
                records = tree.getRecords();//records stil to get
            }
    
            if( records == null ){
                return null;//no records
            }
    
            for ( int i = 0; i < records.length; i++ )
                if ( records[ i ] != null )
                    if ( dumID.equals( records[ i ].getAttributeAsString( "dumID" ) ))
                        return records[ i ];
    
            return null;
        }
    
    }
    As you can see this solution is really unclean and you have to make sure:

    - build function must be called after datasource declaration, a datasource may not be bound to a databound element inside constructor.
    - Better use FetchMode.LOCAL mode in order not to generate network traffic just to get records.

    I would really appreciate if someone else could provide a better solution.

    Yary

    Comment


      #3
      No need for any of this.. DataSource.fetchData() has a callback you can specify, and the data is available to you there (from the DSResponse).

      Comment


        #4
        The callback on DataSource.fetchData will work for intercepting records as they come in, but the records aren't currently accessible after they hit the DataSource; the JavaScript functionality for retrieving a Record by ID isn't exposed to the API. yary's method does provide a way to do that, but the ability to make the lookup directly is very much desired.

        Comment


          #5
          If the records cached in the DataSource (client only or cacheAllData:true DataSource), fetchData() will retrieve them from the local cache. Pass the ID via the criteria argument.

          If the records are not in the DataSource, then they are only accessible from individual components (by design), but fetchData() can retrieve a single record from the server, again by passing the ID as Criteria.

          Comment


            #6
            Originally posted by Isomorphic
            No need for any of this.. DataSource.fetchData() has a callback you can specify, and the data is available to you there (from the DSResponse).
            Ok yes it work with your trick:
            DataSource userDS = DataSource.get("user");
            DSCallback dsCallback = new DSCallback() {
            public void execute(DSResponse response, Object rawData, DSRequest request) {
            Record r = response.getData()[0];
            user = new User();
            user.setName(r.getAttributeAsString("name"));
            user.setRead(r.getAttributeAsBoolean("read"));
            user.setWrite(r.getAttributeAsBoolean("write"));
            user.setAdmin(r.getAttributeAsBoolean("admin"));
            launchApplication();
            }
            };
            userDS.fetchData(new Criteria(), dsCallback);
            It is non blocking, but I got a work around...

            Any trick to do that type of stuff in blocking mode?

            Comment


              #7
              Originally posted by Isomorphic
              If the records cached in the DataSource (client only or cacheAllData:true DataSource), fetchData() will retrieve them from the local cache. Pass the ID via the criteria argument.

              If the records are not in the DataSource, then they are only accessible from individual components (by design), but fetchData() can retrieve a single record from the server, again by passing the ID as Criteria.
              The method with the callback work. But I explore just to understand more!

              Do we absolutely need a criteria? What if we want to just get all the data?

              Would a blank criteria work?

              Code:
              DataSource userDS = DataSource.get("user");
              userDS.setCacheAllData(true);
              userDS.fetchData(new Criteria());
              Record r = userDS.getCacheData()[0];
              User user = new User();
              user.setName(r.getAttributeAsString("Name"));
              user.setRead(r.getAttributeAsBoolean("Read"));
              user.setWrite(r.getAttributeAsBoolean("Write"));
              user.setAdmin(r.getAttributeAsBoolean("Admin"));
              launchApplication();
              Just try this without sucess, index out of bound...

              Comment


                #8
                All network operations are asynchronous. If you want to access cacheData, then you still need to wait for the fetchData callback to fire.

                Yes, blank criteria is fine and will fetch all rows.

                Comment


                  #9
                  jgauthier,

                  The fact that RPC is asyncronous is a mindset that we have to adapt to so no blocking calls when you want to get data from the server. You seem to be dong something that I had to do when i wanted to get the authenticated user from the server before drawing the UI. I think what you have there is the way to block with asyncronous calls. Just put a method call at the end of your DSCallback execute method to do anything that you want to happen after the callback has completed.


                  I have been thinking about an alternate way defer some operations until after the callback has completed but not block drawing the UI. Instead of drawing the UI from the last statement of the DSCallback execute(). Using googles EventBus to fire an event when the callback is complete and then any components, presenters, models etc can register for that event type and do something when the callback has completed. Care would be required to only use this for things that you dont mind displaying to the user in their default state before the callback has completed and the UI updates, preferably changes that the user will not see on initial load.

                  Comment

                  Working...
                  X