Announcement

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

    Treegrid field does not show displayfield value

    Hi,

    I have a Datasource Location with a foreign key relation to Datasource LocationType.

    In A Location TreeGrid, I want to show location records together with the description of their linked LocationType record.

    The problem is that the TreeGrid shows the Id of the LocationType and not the Description, however if you doubleclick the tree row, you get a SelectItem and there it shows the correct picklist of locationtype descriptions. Once you opened the select item once on a row and close it again, the id is replaced with the description.
    (So the problem only seems to be that initially the display fields are not fetched)

    Source:
    TreeGridField typeField = new TreeGridField("locationTypePk", "Type");
    typeField.setAutoFetchDisplayMap(true);
    typeField.setOptionDataSource(DataSources.get("LocationType"));
    typeField.setDisplayField("lctp_description");

    DS Location
    <field type="integer" name="locationTypePk" foreignKey="LocationType.lctp_pk" title=""></field>

    DS LocationType
    <field primaryKey="true" type="sequence" name="lctp_pk" hidden="true" canEdit="false"></field>
    <field type="text" length="45" name="lctp_description" title="" ></field>


    I thought typeField.setAutoFetchDisplayMap(true) would fix this problem but no luck so far.

    Thanks for your help
    David
    Attached Files

    #2
    Try using setValueField(). It looks like it could be automatically detect in this case, but perhaps is not.

    Also check the RPC tab of the Developer Console to see if a request is being issued by the grid for the optionDataSource and whether valid data is returned.

    Comment


      #3
      Sorry to revive this old thread, but I think I've encountered the same problem. Using smartgwt 2.4 with firefox I tried to add an optionDataSource to my tree grid. The code is:

      Code:
      final TreeGrid treeGrid = new TreeGrid();
      treeGrid.setDataSource(dataSource);
      treeGrid.setAutoFetchData(true);
      treeGrid.setLoadDataOnDemand(false);
      treeGrid.setShowOpenIcons(true);
      
      // ****** option data source related properties
      treeGrid.setUseAllDataSourceFields(true);
      TreeGridField treeGridField = new TreeGridField();
      treeGridField.setName("defaultProductType");
      treeGridField.setAutoFetchDisplayMap(true);
      treeGridField.setOptionDataSource(RestDataSourceFactory.createProductTypeDS());
      treeGridField.setValueField("_id");
      treeGridField.setDisplayField("title");
      treeGrid.setFields(treeGridField);
      // ****** end of option source related properties
      treeGrid.setAutoFetchDisplayMap(true);
      It actually works, but displays the value of "defaultproductType" attribute, instead of doing a lookup on the option data source.

      Three observations:
      1. The lookup on ProductTypeDS DOES NOT fire (confirmed using Firebug).
      2. If I edit a row in the tree (.startEditing()), it populates the dropdown in TreeGrid with values for the field in question, and saves the selected value correctly.
      3. If I change the TreeGrid -> ListGrid, it displays the values correctly.

      This raises a question, is there a known issue with TreeGrid? Are there workarounds for this? I have quite a few lookups I'd rather do using optionDataSources instead of populating valueMaps manually.

      thanks in advance,
      Andrius J.

      Comment


        #4
        No known problem here, and because you've got a RestDataSource involved we can't tell if possibly it's faulty, or the problem is elsewhere in the TreeGrid definition - see if you can reproduce a problem starting from a Showcase example.

        Comment


          #5
          OK, here's a simple test case. REST DSs replaced with local ones and static data. Still same behavior. Also, if you uncomment this line

          Code:
          final ListGrid grid = new ListGrid();
          in the code below, the values from option datasource are retrieved correctly.


          Code:
          package com.ajaxelements.client;
          
          import com.google.gwt.core.client.EntryPoint;
          import com.smartgwt.client.data.DataSource;
          import com.smartgwt.client.data.DataSourceField;
          import com.smartgwt.client.data.Record;
          import com.smartgwt.client.data.fields.DataSourceTextField;
          import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
          import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
          import com.smartgwt.client.widgets.tree.TreeGrid;
          import com.smartgwt.client.widgets.tree.TreeGridField;
          import com.smartgwt.client.widgets.tree.TreeNode;
          
          
          public class AjaxElementsDemo implements EntryPoint {
          
              DataSource createCategoryDS() {
                  DataSource ds = new DataSource();
                  ds.setClientOnly(true);
                  ds.addData(createCategoryRec("Root category", "1", null, "type1"));
                  ds.addData(createCategoryRec("Child category", "2", "1", "type2"));
                  ds.addData(createCategoryRec("Second root", "3", null, "type2"));
                  ds.addData(createCategoryRec("Second child", "4", "3", "type2"));
                  ds.setID("CATEGORIES");
                  DataSourceField id = new DataSourceTextField("_id", "ID");
                  DataSourceField title = new DataSourceTextField("title", "Title");
                  DataSourceField parentId = new DataSourceTextField("parentId", "Parent id");
          
                  parentId.setForeignKey("CATEGORIES._id");
                  parentId.setRootValue((String) null);
                  DataSourceField productType = new DataSourceTextField("defaultProductType", "Product type");
                  ds.setFields(id, title, parentId, productType);
                  return ds;
              }
          
              DataSource createProductTypeDS() {
                  DataSource ds = new DataSource();
                  ds.setClientOnly(true);
                  ds.addData(createProductTypeRec("type1", "Monitors"));
                  ds.addData(createProductTypeRec("type2", "CPUs"));
                  ds.setID("PRODUCT_TYPES");
                  DataSourceField id = new DataSourceTextField("_id", "ID");
                  DataSourceField title = new DataSourceTextField("title", "Title");
                  ds.setFields(id, title);
                  return ds;
              }
          
              private Record createProductTypeRec(String id, String title) {
                  Record r1 = new Record();
                  r1.setAttribute("title", title);
                  r1.setAttribute("_id", id);
                  return r1;
              }
          
              private Record createCategoryRec(String title, String id, String parentId, String productTypeId) {
                  Record r1 = new TreeNode();
                  r1.setAttribute("title", title);
                  r1.setAttribute("_id", id);
                  r1.setAttribute("parentId", parentId);
                  r1.setAttribute("defaultProductType", productTypeId);
                  return r1;
              }
          
              public void onModuleLoad() {
                  final TreeGrid grid = new TreeGrid();
                  grid.setLoadDataOnDemand(false);
          //            final ListGrid grid = new ListGrid();
                  grid.setWidth("800px");
                  grid.setHeight("500px");
                  grid.setDataSource(createCategoryDS());
                  grid.setAutoFetchData(true);
                  grid.setUseAllDataSourceFields(true);
                  // ****** option data source related properties
                  TreeGridField treeGridField = new TreeGridField();
                  treeGridField.setName("defaultProductType");
                  treeGridField.setAutoFetchDisplayMap(true);
                  treeGridField.setOptionDataSource(createProductTypeDS());
                  treeGridField.setValueField("_id");
                  treeGridField.setDisplayField("title");
                  grid.setFields(treeGridField);
                  grid.setAutoFetchDisplayMap(true);
                  grid.addRecordClickHandler(new RecordClickHandler() {
                      public void onRecordClick(RecordClickEvent recordClickEvent) {
                          grid.startEditing();
                      }
                  });
                  // ****** end of option source related properties
                  grid.draw();
              }
          }
          If that's not enough, I can send you a trivial maven/intellij project to run this sample, this site doesn't accept zip uploads.

          Ideas? Any help would be appreciated.

          regards,
          Andrius J.

          Comment


            #6
            Confirmed, this is a limitation for the tree field only (the field that shows tree structure). A simple workaround is to fetch record from the related DS using DataSource.fetchData(), and form a valueMap in the callback, assigning the TreeGridField.

            Comment


              #7
              Just to doublecheck - the field in question
              Code:
              TreeGridField treeGridField = new TreeGridField();
              does not have to be a TreeGridField, I might as well use a ListGridField (_id, parentId and title fields are used to display the tree). Changing it to a ListGridField has no effect though.

              Also, should 'limitation' in this case be read as 'missing feature', 'bug' or 'by design'? Meaning, will it be fixed sometime in the future? :)

              regards,
              Andrius J.

              Comment


                #8
                This ended up being a bit trickier than expected, as I'd need to resynchronize the valueMaps with the changes in the datasources. I can probably extend the datasource, and track it's usages in different components, but this looks like a a nasty hack upon a very decent architecture. A simple statement to this question would be enough to guide me:

                [quote]
                Also, should 'limitation' in this case be read as 'missing feature', 'bug' or 'by design'? Meaning, will it be fixed sometime in the future? :)
                [quote]

                regards,
                Andrius J.

                Comment


                  #9
                  This will be fixed, but we don't have an ETA.

                  As far as doing this manually - use a ResultSet - it has a DataChanged event when any component modifies the dataset. When that event fires, re-derive the ValueMap.

                  Comment


                    #10
                    Thanks, good stuff. Should be easy enough to return to the standard behavior once this gets fixed.

                    regards,
                    Andrius J.

                    Comment


                      #11
                      I still have a bit of a chicken-and-egg problem. According to your suggestion, I'm populating the DataSourceEnumField's valueMap like this:

                      Code:
                              final DataSource categoryDs = createDs(CATEGORIES);
                      
                              final DataSourceEnumField defaultProductType = new DataSourceEnumField("defaultProductType", "Product type");
                              // fetch all product types 
                              createProductTypeDS().fetchData(new AdvancedCriteria(), new DSCallback() {
                                  @Override
                                  public void execute(DSResponse response, Object rawData, DSRequest request) {
                      // populate the valueMap                
                                       defaultProductType.setValueMap(response.getDataAsRecordList().getValueMap("_id", "title"));
                                  }
                              });
                              // more fields
                      When I open the TreeGrid that uses this datasource for the first time, I see IDs instead of the values in the defaultProductType column, I am getting the following exception when editing the item inside the grid:

                      Code:
                      ERROR: 02:17:42.064:MDN6:WARN:validation:isOneOf validator specified with no specified list of options or valueMap - validator will always fail. Field definition:{name: "defaultProductType",
                      autoFetchDisplayMap: true,
                      optionDataSource: "producttypes",
                      valueField: "_id",
                      displayField: "title",
                      type: "enum",
                      title: "Product type",
                      validators: Array[1],
                      align: "left",
                      masterIndex: 5,
                      }. com.smartgwt.client.core.JsObject$SGWT_WARN: 02:17:42.064:MDN6:WARN:validation:isOneOf validator specified with no specified list of options or valueMap - validator will always fail. Field definition:{name: "defaultProductType",
                      autoFetchDisplayMap: true,
                      optionDataSource: "producttypes",
                      valueField: "_id",
                      displayField: "title",
                      type: "enum",
                      title: "Product type",
                      validators: Array[1],
                      align: "left",
                      masterIndex: 5,
                      Which kind-of makes sense, since the value map hasn't been populated yet, that's being done in an async callback. If I close and open the same grid again, values are displayed just fine, and everything works correctly.

                      Any further insight would be greatly appreciated.

                      regards,
                      Andrius J.

                      Comment


                        #12
                        We actually recommend placing the ValueMap on the TreeGridField, not the DataSourceField. The result you're getting would be expected if you were trying to modify the field definition after some component had bound to the DataSource.

                        Comment

                        Working...
                        X