Announcement

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

    Update Record Component in ListGrid

    Hi,

    I am working with an issue to update a row in a ListGrid. One of the columns is a Record Component and I have overriden ListGrid.createRecordComponent() and ListGrid.updateRecordComponent() so that it works properly (the record component and other fields display their correct value) when new rows of data are given to the ListGrid. For some reason though, when I update an attribute/cell of a row, all cells in the row are updated, except for the cell containing the record component. This is because in "createRecordComponent", the passed attribute "colNum" never equals to the colNum that the record component corresponds to. Neither is updateRecordComponent ever called during this update of data.

    Therefore, I wonder how we are supposed to update record components when a record in the ListGrid gets new data. Am I perhaps missing something essential?

    I realise that perhaps you need more information about my code if you do not quite understand the issue I am having nor what could be the cause of it. If so, just tell me and I will try and post a test case to recreate the behaviour as well as post what versions of SmartGWT and SmartClient I am using.

    #2
    Hi HenrikAlk,

    do you use setShowRecordComponentsByCell(true)? Also, I get the fieldname like this:

    Code:
            setShowRecordComponents(true);
            setShowRecordComponentsByCell(true);
            setRecordComponentPoolingMode(RecordComponentPoolingMode.RECYCLE);
            setPoolComponentsPerColumn(true);
    
    
    
        @Override
        public Canvas updateRecordComponent(ListGridRecord record, Integer colNum, Canvas component, boolean recordChanged) {
            if (record.getIsGroupSummary())
                return null;
    
            String fieldName = this.getFieldName(colNum);
    ...
    ...
    Best regards
    Blama

    Comment


      #3
      Hi Blama,

      Yes, I set all of those attributes as you show in your code and I can get the fieldName from each of the columns, but for some reason it skips the colNum where the record component is located.

      I update the row accordingly:

      Code:
                      AssignmentStatus aStatus = (AssignmentStatus) object;
                      Record record = resultRecordList.find(SearchPanelColumn.ASTATUS_ID.getAttribute(), aStatus.getObjectID());
                      SearchResult searchResult = (SearchResult) record.getAttributeAsObject(SearchPanelColumn.RESULT_OBJECT.getAttribute());
                      searchResult.aStatus.setStatus(aStatus.getStatus());
      
                      StatusCode displayedStatus = TaskPanelUtil.getDisplayedAStatus(searchResult.aStatus);
                      record.setAttribute(SearchPanelColumn.STATUS.getAttribute(), displayedStatus);
                      record.setAttribute(SearchPanelColumn.CAR.getAttribute(), "Some car");
      
                      sResultTable.markForRedraw();
      where object is the new object containing the new data.

      Kind regards
      Henrik

      Comment


        #4
        Hi HenrikAlk,

        at some point you need to return a Canvas. My code looks like this:
        Code:
            @Override
            protected Canvas createRecordComponent(final ListGridRecord record, Integer colNum) {
                return updateRecordComponent(record, colNum, null, true);
            }
        
            @Override
            public Canvas updateRecordComponent(ListGridRecord record, Integer colNum, Canvas component, boolean recordChanged) {
                if (record.getIsGroupSummary())
                    return null;
        
                String fieldName = this.getFieldName(colNum);
                if (myLGF.getName().equals(fieldName)) {
                    if (component != null) {
                        MyButton mtplb = (MyButton) component;
                        mtplb.setData(record);
                        return mtplb;
                    } else {
                        return new MyButton(record);
                    }
                } else if....
        Best regards
        Blama

        Comment


          #5
          Hello Blama

          Yes, I do do that. Here is how my createRecordComponent and UpdateRecordComponent looks:

          Code:
                  @Override
                  protected Canvas createRecordComponent(final ListGridRecord record, Integer colNum) {
                      String field = this.getFieldName(colNum);
                      final SearchResult res = (SearchResult) record.getAttributeAsObject(VehiclesPanelColumn.RESULT_OBJECT.getAttribute());
          
                      if (field.equals(SearchPanelColumn.STATUS.getAttribute())) {
                          return new StatusRecordComponent(res);
                      }
                      else {
                          return null;
                      }
                  }
          
                  @Override
                  public Canvas updateRecordComponent(ListGridRecord record, Integer colNum, Canvas component,
                          boolean recordChanged) {
                      if(component instanceof StatusRecordComponent && recordChanged) {
                          StatusRecordComponent statusRecordComponent = (StatusRecordComponent) component;
                          SearchResult res = (SearchResult) record.getAttributeAsObject(SearchPanelColumn.RESULT_OBJECT.getAttribute());
                          statusRecordComponent.updateComponent(res);
                          return statusRecordComponent;
                      }
                      else {
                          return super.updateRecordComponent(record, colNum, component, recordChanged);
                      }
                  }
          However, field.equals(SearchPanelColumn.STATUS.getAttribute()) is never true when a record has been updated with new data.

          Regards,
          Henrik

          Comment


            #6
            Hi,

            OK, no real idea. The column is a normal ListGridField with a normal name e.g. "searchRC" or stuff like that and is normally added to the ListGrid with setFields()?
            What do you see then in that column? Is it just empty?
            Are your breakpoints hit as expected in createRecordComponent() / updateRecordComponent()?

            Best regards
            Blama

            Comment


              #7
              Hi Blama ,

              The column is not empty because the createRecordComponent is called correctly when a record is added to the ListGrid/RecordList. However, when a record is updated in the RecordList, createRecordComponent is not called as I would expect it to. The result is that the column is just displaying the value it had before it was updated, as if nothing has happend.

              I setup the ListGridField in question like this:
              Code:
              field.setCellFormatter(new CellFormatter() {
                               ListGridField field = new ListGridField(column.getAttribute(), column.getHeader());
              
                              field.setCellFormatter(new CellFormatter() {
              
                                  @Override
                                  public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
                                      return "";
                                  }
                              });
                             field.setCanFilter(true);
                             SelectItem status = new SelectItem();
                             field.setFilterEditorProperties(status);
                             sResultTable.setFields(field);
              The breakpoints do hit correctly for createRecordComponent() as I understand it. However, I am not entirely certain as to when updateRecordComponent() should be run. It sais it should run when record components are to be applied to a different a record in the grid and needs to be updated. However, can an update of a record be seen as moving the record components to this "new" version of the record and should be run? If so, updateRecordComponent is not run correctly.
              I shall try to study the problem more thoroughly tomorrow.

              Kind Regards,
              Henrik

              Comment


                #8
                Hi HenrikAlk,

                updateRecordComponent() should be run when you scroll the ListGrid and it "recycles" existing objects that are then out of view (see the docs for the 4 APIs in my code in #2).
                IMHO your code looks similar to mine, so I'm not sure where is issue might be.

                Best regards
                Blama

                Comment


                  #9
                  Hi Blama

                  I have managed to solve the issue with a solution of my own. What I do is that I save the recordComponent in the record and when I want to update it I simply retrieve it from the record and update the values as I please.
                  I created a stand alone test class for this. Here is the code for it if anyone run in to the same issue.

                  Code:
                  import com.smartgwt.client.data.Record;
                  import com.smartgwt.client.data.RecordList;
                  import com.smartgwt.client.types.RecordComponentPoolingMode;
                  import com.smartgwt.client.widgets.Canvas;
                  import com.smartgwt.client.widgets.IButton;
                  import com.smartgwt.client.widgets.Label;
                  import com.smartgwt.client.widgets.Window;
                  import com.smartgwt.client.widgets.events.ClickEvent;
                  import com.smartgwt.client.widgets.events.ClickHandler;
                  import com.smartgwt.client.widgets.grid.CellFormatter;
                  import com.smartgwt.client.widgets.grid.ListGrid;
                  import com.smartgwt.client.widgets.grid.ListGridField;
                  import com.smartgwt.client.widgets.grid.ListGridRecord;
                  import com.smartgwt.client.widgets.layout.HLayout;
                  
                  public class TestGrid extends Window {
                  
                      ListGrid testGrid;
                      RecordList recordList;
                      static int cnt = 0;
                  
                      public TestGrid() {
                          createData();
                          setupGUI();
                      }
                  
                      private void setupGUI() {
                          setIsModal(true);
                          setWidth(1000);
                          setHeight(800);
                          centerInPage();
                          setTitle("Test grid");
                  
                          setupListGrid();
                          setupButtons();
                      }
                  
                      private void setupListGrid() {
                          testGrid = new ListGrid() {
                  
                              @Override
                              public Canvas updateRecordComponent(ListGridRecord record, Integer colNum, Canvas component,
                                      boolean recordChanged) {
                                  if(component instanceof TestRecordComponent && recordChanged) {
                                      TestRecordComponent testRecordComponent = new TestRecordComponent(
                                              record.getAttribute(TestGridColumn.RC_DATA_FOR_OBJECT.attribute));
                                      return testRecordComponent;
                                  } else {
                                      return super.updateRecordComponent(record, colNum, component, recordChanged);
                                  }
                              }
                  
                              @Override
                              protected Canvas createRecordComponent(ListGridRecord record, Integer colNum) {
                                  String field = this.getFieldName(colNum);
                  
                                  if(field.equals(TestGridColumn.RC.attribute)) {
                                      TestRecordComponent trc = new TestRecordComponent(record.getAttribute(TestGridColumn.RC_DATA_FOR_OBJECT.attribute));
                                      record.setAttribute(TestGridColumn.RC_OBJECT.attribute, trc); // The recordComponent is saved in the record here
                                      return trc;
                                  } else {
                                      return null;
                                  }
                              }
                          };
                          testGrid.setShowRecordComponents(true);
                          testGrid.setShowRecordComponentsByCell(true);
                          testGrid.setRecordComponentPoolingMode(RecordComponentPoolingMode.RECYCLE);
                          testGrid.setPoolComponentsPerColumn(true);
                          testGrid.setData(recordList);
                          testGrid.setSnapToGrid(true);
                          testGrid.setShowFilterEditor(true);
                          testGrid.setWidth100();
                          testGrid.setHeight100();
                  
                          setupColumns();
                  
                          addItem(testGrid);
                      }
                  
                      private void setupColumns() {
                          ListGridField[] listgridFields = new ListGridField[TestGridColumn.values().length];
                          int i = 0;
                          for (TestGridColumn testGridColumn : TestGridColumn.values()) {
                              ListGridField listGridField = new ListGridField(testGridColumn.attribute, testGridColumn.title);
                              listgridFields[i++] = listGridField;
                              switch(testGridColumn) {
                              case RC:
                                  listGridField.setCellFormatter(new CellFormatter() {
                  
                                      @Override
                                      public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
                                          return "";
                                      }
                                  });
                                  break;
                              case RC_DATA_FOR_OBJECT:
                              case RC_OBJECT:
                                  listGridField.setHidden(true);
                                  break;
                              default:
                                  break;
                              }
                          }
                          testGrid.setFields(listgridFields);
                      }
                  
                      private void setupButtons() {
                          IButton updateBtn = new IButton("Update row");
                          updateBtn.addClickHandler(new ClickHandler() {
                  
                              @Override
                              public void onClick(ClickEvent event) {
                                  updateSelectedRow();
                              }
                          });
                          addItem(updateBtn);
                      }
                  
                      protected void updateSelectedRow() {
                          if(testGrid.getSelectedRecord() != null) {
                              ListGridRecord selectedRecord = testGrid.getSelectedRecord();
                              Record record = recordList.find(TestGridColumn.ID.attribute, selectedRecord.getAttribute(TestGridColumn.ID.attribute));
                              record.setAttribute(TestGridColumn.TEXT.attribute, "updated " + cnt++);
                              record.setAttribute(TestGridColumn.RC_DATA_FOR_OBJECT.attribute, "Update that is now seen");
                              record.setAttribute(TestGridColumn.ID.attribute, selectedRecord.getAttribute(TestGridColumn.ID.attribute));
                              TestRecordComponent trc = (TestRecordComponent) record.getAttributeAsObject(TestGridColumn.RC_OBJECT.attribute);
                              trc.label.setContents(record.getAttribute(TestGridColumn.RC_DATA_FOR_OBJECT.attribute)); // The recordComponent is updated here
                              testGrid.markForRedraw();
                          }
                      }
                  
                      private void createData() {
                          recordList = new RecordList();
                          for(int i = 0; i < 3; i++) {
                              Record record = new Record();
                              for (TestGridColumn testGridColumn : TestGridColumn.values()) {
                                  if(testGridColumn.equals(TestGridColumn.RC))
                                      record.setAttribute(testGridColumn.attribute, "");
                                  else
                                      record.setAttribute(testGridColumn.attribute, "value" + i);
                              }
                              recordList.add(record);
                          }
                      }
                  
                      private enum TestGridColumn {
                          ID("ID", "id"),
                          RC("RC test", "rc"),
                          RC_DATA_FOR_OBJECT("", "rc_data"),
                          RC_OBJECT("", "rc_object"),
                          TEXT("Text", "text");
                  
                          public String title;
                          public String attribute;
                  
                          private TestGridColumn(String title, String attribute) {
                              this.title = title;
                              this.attribute = attribute;
                          }
                      }
                  
                      private class TestRecordComponent extends HLayout {
                          private Label label;
                  
                          public TestRecordComponent(String text) {
                              label = new Label(text);
                              label.setWrap(false);
                              label.setWidth100();
                              addMember(label);
                          }
                      }
                  }

                  Comment


                    #10
                    Hi HenrikAlk,

                    with this code you are always returning a new object from updateRecordComponent(). IMHO this will remove the effect of setRecordComponentPoolingMode(RecordComponentPoolingMode.RECYCLE) as far as I understand it.
                    I'd do sth. like this:
                    Code:
                     if (component instanceof TestRecordComponent) {
                    TestRecordComponent newComp = (TestRecordComponent) component;
                    newComp.someSetter(record);
                    return newComp;
                    }
                    Also I don't know why you have the problem with the column-id. But I assume that it is faster to only take action in updateRecordComponent() if you are in the correct column.
                    Perhaps create a testcase to show the problem with that you describe in #3.

                    Best regards
                    Blama

                    Comment

                    Working...
                    X