Announcement

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

    ListGrid.selectSingleRecord(selectedRecord) issue

    I am using SmartGWT 4.0 on Firefox.
    I use ListGrid.selectSingleRecord(selectedRecord) to select a single record, and it works.
    But when I use the command again, the new record is selected, but the previous one doesn't get deselected.

    #2
    We've just tried to reproduce this issue using the latest SmartGWT 4.0p release available but we're not having any luck.

    Could you please provide a full test case in order for us to reproduce?

    Regards,
    Isomorphic Software

    Comment


      #3
      Here is the code to reproduce the issue

      // It is a client only cache
      mUserListDataSource.setClientOnly(true);
      // Add a new record
      mUserListDataSource.addData(record);
      mUserListDataSource.fetchData();
      mListGrid.selectSingleRecord(record);
      // The selection works
      mUserListDataSource.addData(anotherRcord);
      mUserListDataSource.fetchData();
      mListGrid.selectSingleRecord(anotherRcord);
      // Both record and anotherRcord are selected

      Comment


        #4
        As you've not provided more code to understand the context we've tried to simulate what you've described using the below code but still cant reproduce this issue.

        Every time you click the New Record button a new record is added to the list and selectSingleRecord called on that new record, this in turn makes the previous selected item unselected and the new record selected.

        Could you possibly provide a FULL test case for this issue or alter the code below in order for us to reproduce?

        Code:
            public void onModuleLoad() {
                final DataSource dataSource = new DataSource();
                dataSource.setFields(new DataSourceTextField("name"));
                dataSource.setClientOnly(true);
        
                final VLayout layout = new VLayout();
                layout.setWidth("100%");
                layout.setHeight("100%");
        
                final ListGrid listGrid = new ListGrid(dataSource);
                listGrid.setWidth("30%");
                layout.addMember(listGrid);
        
                final IButton button = new IButton("New Record");
                button.addClickHandler(new ClickHandler() {
                    private int recordNumber = 0;
        
                    public void onClick(ClickEvent event) {
                        final Record record = new Record();
                        record.setAttribute("name", "Record " + recordNumber++);
        
                        listGrid.addData(record);
                        listGrid.fetchData();
                        listGrid.selectSingleRecord(record);
                    }
                });
        
                layout.addMember(button);
        
                layout.draw();
            }
        Regards,
        Isomorphic Software

        Comment


          #5
          Double rows are selected

          public void onModuleLoad() {
          final DataSource dataSource = new DataSource();
          dataSource.setFields(new DataSourceTextField("name"));
          dataSource.setClientOnly(true);

          final VLayout layout = new VLayout();
          layout.setWidth("100%");
          layout.setHeight("100%");

          final ListGrid listGrid = new ListGrid(dataSource);
          listGrid.setWidth("30%");
          layout.addMember(listGrid);

          final IButton button = new IButton("New Record");
          button.addClickHandler(new com.smartgwt.client.widgets.events.ClickHandler() {
          private int recordNumber = 0;

          public void onClick(ClickEvent event) {
          final Record record = new Record();
          record.setAttribute("name", "Record " + recordNumber++);
          listGrid.addData(record);
          listGrid.fetchData();
          listGrid.selectSingleRecord(record);
          final Record secondRecord = new Record();
          secondRecord.setAttribute("name", "Record " + recordNumber++);
          listGrid.addData(secondRecord);
          listGrid.fetchData();
          listGrid.selectSingleRecord(secondRecord);
          }
          });

          layout.addMember(button);

          layout.draw();
          }

          Comment


            #6
            First or all, apologies for the poor code example. In hindsight I now realise that making a call to fetchData right after addData makes no sense and it's actually a bit strange that it works at all.

            It's very likely that you will be running into a race condition doing this as the data might not have been added before the fetchData call is made. Same thing when it comes to the selectSingleRecord, when doing this right after fetchData you should get a warning that selectSingleRecord has been ignored because a fetch operation is in progress.

            Could you please explain a bit further what you're trying to do and why?

            Comment


              #7
              Explaination

              First or all, apologies for the poor code example. In hindsight I now realise that making a call to fetchData right after addData makes no sense and it's actually a bit strange that it works at all.
              ==> Without fetchData, the table is not updated.

              It's very likely that you will be running into a race condition doing this as the data might not have been added before the fetchData call is made. Same thing when it comes to the selectSingleRecord, when doing this right after fetchData you should get a warning that selectSingleRecord has been ignored because a fetch operation is in progress.
              ==> I set the breakpoint between the two fetchData. I make sure the first one finishes (I even cleaned it), but the second one still select the first one.

              ==> Why do I do this? I add a new record through a separator command. I need to retrieve all new data and select the newly added/edited data.

              Comment


                #8
                I need to add a few records, one at a time. Each adding needs to select the newly added records.
                In fact, my table is a single selected one.

                Comment


                  #9
                  The problem

                  This is exactly the problem. I need to update the existing record, and add the new record. The selection of the new record will select all previous ones.

                  public void onModuleLoad() {
                  final DataSource dataSource = new DataSource();
                  DataSourceTextField tf = new DataSourceTextField("name");
                  tf.setPrimaryKey(true);
                  dataSource.setFields(tf);
                  dataSource.setClientOnly(true);

                  final VLayout layout = new VLayout();
                  layout.setWidth("100%");
                  layout.setHeight("100%");

                  final ListGrid listGrid = new ListGrid(dataSource);
                  listGrid.setWidth("30%");
                  layout.addMember(listGrid);
                  final List<Record> records = new ArrayList<Record>();

                  final IButton button = new IButton("New Record");
                  button.addClickHandler(new ClickHandler() {
                  private int recordNumber = 0;

                  public void onClick(ClickEvent event) {
                  final Record record = new Record();
                  record.setAttribute("name", "Record"
                  + recordNumber++);
                  dataSource.addData(record);
                  for (Record rec : records) {
                  dataSource.updateData(rec);
                  }
                  records.add(record);
                  listGrid.fetchData();
                  listGrid.selectSingleRecord(record);
                  }
                  });

                  layout.addMember(button);

                  layout.draw();
                  }

                  Comment


                    #10
                    When you call DataSource.addData() or updateData(), any grid bound to that DataSource will automatically show the new record because of automatic cache sync - see ListGrid.fetchData() and the related ResultSet docs.

                    So you do not need to call fetchData() after addData() or updateData().

                    However you *do* need to call fetchData() *once*, when the grid is first created, to set up the ResultSet which will then automatically incorporate further changes. In this (very odd) code snippet, this was not done.

                    Finally, to reiterate, it would *always* be invalid to call addData() and then immediately try to select the added record.

                    Firstly, addData() is an asynchronous process which may fail, so you need to use the callback argument of addData() to wait until the add operation has actually succeeded.

                    Second, the Record instance passed to addData() is not the same Record instance as the Record that appears in the grid. The Record that appears in the grid is from the server's response, and may contain additional fields that were generated on the server (such as sequence-based primary keys). The callback to addData() gives you access to the server's response, which includes the newly added record data, so you can look up the newly added record by it's primaryKey value (using ResultSet.find() for instance).

                    Comment


                      #11
                      Also, just a further note here - a clientOnly DataSource fully simulates a remote dataset, including requiring you to code as though all operations are asynchronous and could fail, because the purpose of a clientOnly DataSource is to be replaceable will a real DataSource without any code changes.

                      A different way to use the ListGrid is to create a RecordList with the Records you want. You can modify the RecordList directly and synchronously with APIs like RecordList.addAt(). If you are just working with a small set of Records where you don't need paging, filtering, sorting, etc, then using RecordList can be simpler.

                      Comment


                        #12
                        Would you please to fix the code snippet to make the selection work?

                        Comment


                          #13
                          Please take note of the comments in the code.

                          Code:
                              public void onModuleLoad() {
                                  final DataSource dataSource = new DataSource();
                          
                                  // Added a separate sequence field here to demonstrate that this works even though we're
                                  // not explicitly setting the id when we create the record, this is done automatically.
                                  final DataSourceSequenceField idField = new DataSourceSequenceField("id");
                                  idField.setPrimaryKey(true);
                          
                                  dataSource.setFields(idField, new DataSourceTextField("name"));
                                  dataSource.setClientOnly(true);
                          
                                  final VLayout layout = new VLayout();
                                  layout.setWidth("100%");
                                  layout.setHeight("100%");
                          
                                  final ListGrid listGrid = new ListGrid(dataSource);
                                  listGrid.setWidth("30%");
                                  layout.addMember(listGrid);
                          
                                  // After we've create the list grid we call fetchData to initialise the ResultSet
                                  listGrid.fetchData();
                          
                                  final IButton button = new IButton("New Record");
                                  button.addClickHandler(new ClickHandler() {
                                      private int recordNumber = 0;
                          
                                      public void onClick(ClickEvent event) {
                                          // Create a new Record
                                          final Record record = new Record();
                                          record.setAttribute("name", "Record" + recordNumber++);
                          
                                          // Lets call addData with the new record, when the callback is fired we grab the
                                          // added record from the DSResponse and use that when calling selectSingleRecord
                                          dataSource.addData(record, new DSCallback() {
                                              @Override
                                              public void execute(final DSResponse dsResponse, final Object data, final DSRequest dsRequest) {
                                                  listGrid.selectSingleRecord(dsResponse.getData()[0]);
                                              }
                                          });
                                      }
                                  });
                          
                                  layout.addMember(button);
                                  layout.draw();
                              }

                          Comment


                            #14
                            Yes, it works now. Thanks!

                            Comment


                              #15
                              Cannot click to select

                              Now the programmatic selection works, but the manual selection doesn't work any more. After the following code:
                              dataSource.addData(record, new DSCallback() {
                              @Override
                              public void execute(final DSResponse dsResponse, final Object data, final DSRequest dsRequest) {
                              listGrid.selectSingleRecord(dsResponse.getData()[0]);
                              }
                              });

                              When I click on the list grid, getSelectedRecords() returns exception.

                              Here is the code:
                              addSelectionUpdatedHandler(new SelectionUpdatedHandler() {
                              @Override
                              public void onSelectionUpdated(SelectionUpdatedEvent event) {
                              if (mDoSelectionChanges) {
                              setSelectedRecords(getSelectedRecords(), true);
                              }
                              }
                              });

                              Here is the exception:
                              java.lang.ClassCastException: com.smartgwt.client.data.Record cannot be cast to com.smartgwt.client.widgets.grid.ListGridRecord
                              at com.smartgwt.client.util.ConvertTo.arrayOfListGridRecord(ConvertTo.java:3129)
                              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                              at java.lang.reflect.Method.invoke(Method.java:597)
                              at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
                              at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
                              at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
                              at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:338)
                              at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:219)
                              at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
                              at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:571)
                              at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:279)
                              at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
                              at com.smartgwt.client.widgets.grid.ListGrid.getSelectedRecords(ListGrid.java)

                              Comment

                              Working...
                              X