Announcement

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

    Nested ListGrid displays only first line of data

    Hi - I am trying to display a nested ListGrid. I followed the example in the showcase but I must be missing something.

    The main ListGrid loads from Datasource1 and the nested one loads from Datasource2. Both datasources have one field in common.

    Problem: My nested Datasource2 displays only the first line of data, and displays the same line of nested data everywhere (under all high-level elements). Please see attached image for the display that I get. That display is what I want, except for the missing lines of data and the fact that the link between the DS and nested DS is apparently not working in my code.

    Using Smartgwt 4.1p.


    Widget creation
    Code:
    package gov.nist.toolkit.xdstools3.client.customWidgets.endpoints.configure;
    
    import com.smartgwt.client.types.ExpansionMode;
    import com.smartgwt.client.types.ListGridEditEvent;
    import com.smartgwt.client.types.RowEndEditAction;
    import com.smartgwt.client.widgets.grid.ListGrid;
    import com.smartgwt.client.widgets.layout.HLayout;
    
    /**
     *
     * Created by dazais on 5/21/2014.
     */
    public class EndpointsConfigWidget extends HLayout {
        private ListGrid endpointGrid;
        private boolean endpointValueSelected = false;
    
        public EndpointsConfigWidget() {
            endpointGrid = createEndpointGrid();
            addMember(endpointGrid);
        }
    
        public ListGrid createEndpointGrid() {
    
            final ListGrid grid = new ListGrid();
            grid.setHeight(500);
            grid.setWidth(800);
            grid.setAlternateRecordStyles(true);
            grid.setDataSource(EndpointConfigDSNew.getInstance());
            grid.setAutoFetchData(true);
            grid.setDrawAheadRatio(4);
            grid.setCanExpandRecords(true);
            grid.setCanExpandMultipleRecords(true);
             grid.setExpansionMode(ExpansionMode.RELATED);
            grid.setDetailDS(TransactionDS.getInstance()); // other TransactionDS
            grid.setCanEdit(true);
            grid.setModalEditing(true);
            grid.setEditEvent(ListGridEditEvent.CLICK);
            grid.setListEndEditAction(RowEndEditAction.NEXT);
            grid.setAutoSaveEdits(false);
    
            return grid;
        }
    
        }
    Datasource1 (main)
    Code:
    package gov.nist.toolkit.xdstools3.client.customWidgets.endpoints.configure;
    
    import com.smartgwt.client.data.RestDataSource;
    import com.smartgwt.client.data.fields.DataSourceTextField;
    
    /**
     * SmartGWT datasource for accessing entities over http in a RESTful manner.
     * Defines a RESTDataSource fields, operations and REST service URLs.
     */
    public class EndpointConfigDSNew extends RestDataSource {
    
    
        private static EndpointConfigDSNew instance = null;
    
        public static EndpointConfigDSNew getInstance() {
            if (instance == null) {
                instance = new EndpointConfigDSNew();
            }
            return instance;
        }
    
    	private EndpointConfigDSNew() {
            setID("endpointConfigDS");
            setDataURL("resources/datasources/endpoints/_actors.data.xml");
            setRecordXPath("/sites/site"); // this is the path to the record we want to display, inside the XML file holding the data
    
            DataSourceTextField endpointName = new DataSourceTextField("endpointName", "Endpoint Name");
    
            setFields(endpointName);
        }
    }
    Datasource2 (nested)
    Code:
    package gov.nist.toolkit.xdstools3.client.customWidgets.endpoints.configure;
    
    import com.smartgwt.client.data.RestDataSource;
    import com.smartgwt.client.data.fields.DataSourceTextField;
    
    public class TransactionDS extends RestDataSource {
    
        private static TransactionDS instance = null;
    
        public static TransactionDS getInstance() {
            if (instance == null) {
                instance = new TransactionDS();
            }
            return instance;
        }
    
    	private TransactionDS() {
            setID("transactionDS");
            setDataURL("resources/datasources/endpoints/pub-edited.data.xml");
            setRecordXPath("/site"); //the XML path of the element we want to display, in the datasource file (.data.xml)
    
            DataSourceTextField endpointName = new DataSourceTextField("name", "Endpoint Name");
            //System.out.println(endpointName.getValueXPath());
            //endpointName.setHidden(true);
            endpointName.setCanEdit(false);
            endpointName.setForeignKey("endpointConfigDS.endpointName");
    
            DataSourceTextField code = new DataSourceTextField("transaction.code");
            code.setPrimaryKey(true);
            code.setHidden(true);
            DataSourceTextField name = new DataSourceTextField("transaction.name", "Transaction Type", 128, true); // isRequired = true
            DataSourceTextField tls = new DataSourceTextField("transaction.secure", "TLS Endpoint");
            DataSourceTextField notls = new DataSourceTextField("transaction.unsecure", "Non-TLS Endpoint");
    
    
            setFields(code, name, tls, notls, endpointName);
    	}
    }

    Datasource1 XML
    Code:
    <sites>
        <site>
            <endpointName>pub</endpointName>
            <parentID>root</parentID>
        </site>
        <site>
            <endpointName>connect3.3_AMAZON</endpointName>
            <parentID>root</parentID>
        </site>
    </sites>

    Datasource2 XML
    Code:
    <site name="pub">
        <home>urn:oid:1.19.6.24.109.42.1.3</home>
        <transaction code="sq.b" name="Stored Query">
            <secure>https://ihexds.nist.gov:12081/tf6/services/xdsregistryb</secure>
            <unsecure>http://ihexds.nist.gov:12080/tf6/services/xdsregistryb</unsecure>
        </transaction>
        <transaction code="r.b" name="Register">
            <secure>https://ihexds.nist.gov:12081/tf6/services/xdsregistryb</secure>
            <unsecure>http://ihexds.nist.gov:12080/tf6/services/xdsregistryb</unsecure>
        </transaction>
        <repository uid="1.19.6.24.109.42.1.5">
            <secure>https://ihexds.nist.gov:12081/tf6/services/xdsrepositoryb</secure>
            <unsecure>http://ihexds.nist.gov:12080/tf6/services/xdsrepositoryb</unsecure>
        </repository>
    </site>
    If anyone has any pointers as to what I am doing wrong, that would be great.
    Attached Files
    Last edited by darkane; 11 Jul 2014, 07:55. Reason: Code for Datasource2 that shows the common field between the 2 datasources ("Endpoint Name")

    #2
    I think I figured out this one. I will post a full solution later, I just wanted to avoid that people would waste time fixing an issue I know how to solve.

    First of all, I had two issues combined.

    1/ The relationship between main DS and nested DS wasn't working. I could not find a fix for this code:
    Code:
             grid.setExpansionMode(ExpansionMode.RELATED);
            grid.setDetailDS(TransactionDS.getInstance());
    So I transitioned instead to a code closer to the Nested Grid example in the Smartgwt Showcase, based on:
    Code:
     @Override
                protected Canvas getExpansionComponent(final ListGridRecord record) {...}
    This allowed me to at least stop randomly displaying fields that had no relation to my top-level element.

    2/ I believe the structure of my nested datasource is incorrect for the type of display I was trying to achieve. My nested DS has only ONE "site" element which I use with setRecordXPath("/site"). So of course only one element will be displayed, even if I have several "transactions" elements at a lower level. Displaying these transactions is what I was after but I need to rework my model for that.

    I think I will just use the "site" name as a file name for each nested DS data file and remove the XML "site" tag altogether. Note that having one file per "site" is a requirement of my project. I will instead call one nested datasource per component to be opened / extended.

    Feel free to comment if you have any opinion on the best method here.

    Comment


      #3
      Hi,

      in order to make the relation between DS and nested DS working, you have to set setClientOnly(true) on your DS.

      I've modified the DS and XML somewhat (I hope they still match your usecase) and have gotten as far as on the screenshot.

      As you can see, the two nested transaction records of the first record cannot be properly displayed in the list.
      I guess this can be achieved by using the autochild mechanism to set a cell value formatter for the field, so that its properties are properly rendered per record.
      I don't have the time to fiddle that out but let me know of your progress :)

      Regards,
      fatzopilot
      Attached Files

      Comment


        #4
        First of all, thank you a lot for the answer.

        I agree that setClientOnly(true) must be set on the DS in order for it to work. I forgot to mention it, thank you for pointing it out.

        However, your partial solution that uses setMultiple(true) in the DS doesn't work for me because it displays several items in a same cell, separated by a comma. I need all my items ("transactions") to be displayed one per line.

        I managed to get all the items from the XML files to be displayed, but doing that I broke the dependency between DS and nested DS. I think my Xpath expression to get the site name is wrong in the nested DS. Could someone take a look?

        I believe the section of code that is not working is this one:
        Code:
                DataSourceTextField endpointName = new DataSourceTextField("name", "Endpoint Name");
                endpointName.setValueXPath("/site/@name");
        And here's all the rest of the updated code:


        Main XML source
        Code:
        <sites>
            <site>
                <endpointName>pub</endpointName>
            </site>
            <site>
                <endpointName>connect3.3_AMAZON</endpointName>
            </site>
        </sites>
        Main DS
        Code:
        package gov.nist.toolkit.xdstools3.client.customWidgets.endpoints.configure;
        
        import com.smartgwt.client.data.RestDataSource;
        import com.smartgwt.client.data.fields.DataSourceTextField;
        
        /**
         * SmartGWT datasource for accessing entities over http in a RESTful manner.
         * Defines a RESTDataSource fields, operations and REST service URLs.
         */
        public class EndpointConfigDSNew extends RestDataSource {
        
        
            private static EndpointConfigDSNew instance = null;
        
            public static EndpointConfigDSNew getInstance() {
                if (instance == null) {
                    instance = new EndpointConfigDSNew();
                }
                return instance;
            }
        
        	private EndpointConfigDSNew() {
                setID("endpointConfigDS");
                setDataURL("resources/datasources/endpoints/_actors.data.xml");
                setRecordXPath("/sites/site"); // this is the path to the record we want to display, inside the XML file holding the data
                setClientOnly(true);
        
                DataSourceTextField endpointName = new DataSourceTextField("endpointName", "Endpoint Name");
                endpointName.setRequired(true);
                endpointName.setPrimaryKey(true);
        
                setFields(endpointName);
        
            }
        }
        Nested XML source
        Code:
        <site name="pub">
            <home>urn:oid:1.19.6.24.109.42.1.3</home>
            <transaction code="sq.b" name="Stored Query">
                <secure>https://ihexds.nist.gov:12081/tf6/services/xdsregistryb</secure>
                <unsecure>http://ihexds.nist.gov:12080/tf6/services/xdsregistryb</unsecure>
            </transaction>
            <transaction code="r.b" name="Register">
                <secure>https://ihexds.nist.gov:12081/tf6/services/xdsregistryb</secure>
                <unsecure>http://ihexds.nist.gov:12080/tf6/services/xdsregistryb</unsecure>
            </transaction>
            <repository uid="1.19.6.24.109.42.1.5">
                <secure>https://ihexds.nist.gov:12081/tf6/services/xdsrepositoryb</secure>
                <unsecure>http://ihexds.nist.gov:12080/tf6/services/xdsrepositoryb</unsecure>
            </repository>
        </site>
        Nested XML DS
        Code:
        package gov.nist.toolkit.xdstools3.client.customWidgets.endpoints.configure;
        
        import com.smartgwt.client.data.RestDataSource;
        import com.smartgwt.client.data.fields.DataSourceTextField;
        
        /**
         * SmartGWT datasource for accessing entities over http in a RESTful manner.
         * Defines a RESTDataSource fields, operations and REST service URLs.
         */
        public class TransactionDS extends RestDataSource {
        
            private static TransactionDS instance = null;
        
            public static TransactionDS getInstance() {
                if (instance == null) {
                    instance = new TransactionDS();
                }
                return instance;
            }
        
        	private TransactionDS() {
                setID("transactionDS");
                setDataURL("resources/datasources/endpoints/pub-edited.data.xml");
                setRecordXPath("/site/transaction"); //the XML path of the element we want to display, in the datasource file (.data.xml)
                setClientOnly(true);
        
                DataSourceTextField endpointName = new DataSourceTextField("name", "Endpoint Name");
                endpointName.setValueXPath("/site/@name");
               // System.out.println(endpointName.getValueMap());
                //endpointName.setHidden(true);
                endpointName.setCanEdit(false);
                endpointName.setForeignKey("endpointConfigDS.endpointName");
        
                DataSourceTextField code = new DataSourceTextField("code");
                code.setPrimaryKey(true);
                code.setHidden(true);
                DataSourceTextField name = new DataSourceTextField("name", "Transaction Type", 128, true); // isRequired = true
                DataSourceTextField tls = new DataSourceTextField("secure", "TLS Endpoint");
                DataSourceTextField notls = new DataSourceTextField("unsecure", "Non-TLS Endpoint");
        
        
                setFields(code, name, tls, notls, endpointName);
        	}
        }
        Attached Files

        Comment


          #5
          Does outcommenting
          endpointName.setValueXPath("/site/@name");
          help?

          Comment


            #6
            I tried and it gives the same result (null value for that field and the two DSs are not matched, same graphical output), which makes sense since I changed the RecordXPath to setRecordXPath("/site/transaction") in order to display the multiple transactions.

            Now what I need is to access the ancestor /site and its "name" attribute. I tried several combinations of XPath expressions that seemed valid based on the docs, but I keep getting null values for my field "endpoint names".

            Comment


              #7
              Solution

              I solved this. It turns out I did not pay enough attention to logs on the Smartgwt console. The problem came from a duplicate "name" element in my nested xml source file. Once the XML structure was flattened using XPath, both "name" tags had the same representation and were confusing the ListGrid.
              I renamed one of them, both inside the XML and in the DS and it worked.

              In addition to that, I validated my XPath expression using an online validator just to be sure.
              New XPath:
              Code:
               endpointName.setValueXPath("/site/transaction/ancestor::site/@siteName");
              Example of XPath tester:
              http://www.freeformatter.com/xpath-tester.html


              Solution (nested DS):

              Code:
              package gov.nist.toolkit.xdstools3.client.customWidgets.endpoints.configure;
              
              import com.smartgwt.client.data.DataSource;
              import com.smartgwt.client.data.fields.DataSourceTextField;
              
              /**
               * SmartGWT datasource.
               */
              public class TransactionDS extends DataSource {
              
                  private static TransactionDS instance = null;
              
                  public static TransactionDS getInstance() {
                      if (instance == null) {
                          instance = new TransactionDS();
                      }
                      return instance;
                  }
              
              	private TransactionDS() {
                      setID("transactionDS");
                      setDataURL("resources/datasources/endpoints/pub-edited.data.xml");
                      setRecordXPath("/site/transaction"); //the XML path of the element we want to display, in the datasource file (.data.xml)
                      setClientOnly(true);
              
                      DataSourceTextField endpointName = new DataSourceTextField("siteName", "Endpoint Name");
                       endpointName.setValueXPath("/site/transaction/ancestor::site/@siteName");
                     // System.out.println(endpointName.getValueMap());
                     //endpointName.setHidden(true);
                      endpointName.setCanEdit(false);
                      endpointName.setForeignKey("endpointConfigDSNew.endpointName");
              
                      DataSourceTextField code = new DataSourceTextField("code");
                      code.setPrimaryKey(true);
                      code.setHidden(true);
                      DataSourceTextField name = new DataSourceTextField("name", "Transaction Type", 128, true); // isRequired = true
                      DataSourceTextField tls = new DataSourceTextField("secure", "TLS Endpoint");
                      DataSourceTextField notls = new DataSourceTextField("unsecure", "Non-TLS Endpoint");
              
              
                      setFields(code, name, tls, notls, endpointName);
              	}
              }
              Thank you for helping, fatzopilot!
              Attached Files
              Last edited by darkane; 15 Jul 2014, 08:40.

              Comment

              Working...
              X