Announcement

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

    ComboBoxItem setValue() and/or getSelectedRecord() problem

    Hey,

    at least one of those methods doesn't seem to work as expected.

    SmartClient Version: v12.0p_2018-08-22/LGPL Development Only (built 2018-08-22)

    With the code below
    Activity Result Expected result
    Click "Select Item" button Nothing visible You should see "name2" in the combo
    Click "Print selected" button Now "name2" is visible in the combo.
    Null is printed to the console as selected record.
    The selected record should have been printed to the console, not null.
    Click "Print selected" button again Null is printed again to the console as selected record. The selected record should have been printed to the console, not null.
    Click "Print selected" button again The selected record is printed to the console Yay, it happened finally!

    Code:
        public void onModuleLoad() {
    
            MockDataSource ds = new MockDataSource();
            Record r1 = new Record(); 
            r1.setAttribute("name", "name1");
            r1.setAttribute("id", "1");
            Record r2 = new Record();
            r2.setAttribute("name", "name2");
            r2.setAttribute("id", "2");
            ds.setMockData(r1, r2);
    
            ComboBoxItem combo = new ComboBoxItem();  
            combo.setTitle("Select Item");  
            combo.setOptionDataSource(ds);  
            combo.setDisplayField("name");  
            combo.setValueField("id");  
    
            DynamicForm form = new DynamicForm();  
            form.setFields(combo);
    
            Button printButton = new Button("Print selected");
            printButton.addClickHandler(e -> GWT.log("Selected: " + combo.getSelectedRecord()));
    
            Button selectButton = new Button("Select item");
            printButton.addClickHandler(e -> combo.setValue("2"));
    
            VLayout canvas = new VLayout();
            canvas.addMember(form);
            canvas.addMember(selectButton);
            canvas.addMember(printButton);
            canvas.draw();  
        }

    #2
    Your DataSource lacks a primaryKey field, and in fact, field definitions at all.

    You are also inexplicably using MockDataSource - please read the docs on this, it's not intended for direct use within an application you are coding by hand.

    Comment


      #3
      The lack of field definitions doesn't seem to do anything with the subject, however MockDataSource does, we had a totally different problem with the same result which I somehow managed to "reproduce" this weird way. Sorry for the confusion.

      However, a paging problem seems to be found while playing this around:

      If you select an item in ComboBoxItem programatically with setValue() [works fine], then drop down the ComboBoxItem, it fetches data only once, if the selected is in the response then it is selected in the list as expected, if not, it it won't fetch more data.

      Stepts to reproduce with the code + ds.jsp below:
      1. Click "Select item" button: you will see a request to the server for the specific record of id 90, and it is displayed in the combo box as expected.
      2. Drop down the combo box
        • result: you will see another request for the rows 0-75 (the record with id 90 is not returned in the response), and the first item is selected in the list
        • expected: two server requests, first for rows 0-75 and a second for rows 76-xx, and "name90" should be selected in the list
      3. If you scroll down manually so that "name90" is fetched, then close up and drop down again, then "name90" will be selected in the list as expected
      SmartClient Version: v12.0p_2018-08-22/LGPL Development Only (built 2018-08-22)

      Code:
          public void onModuleLoad() {
      
              ComboBoxItem combo = new ComboBoxItem();  
              combo.setTitle("Select Item");  
              combo.setOptionDataSource(new SomeDS());  
              combo.setDisplayField("name");  
              combo.setValueField("id");  
      
              DynamicForm form = new DynamicForm();  
              form.setFields(combo);
      
              Button selectButton = new Button("Select item");
              selectButton.addClickHandler(e -> combo.setValue("90"));
      
              VLayout canvas = new VLayout();
              canvas.addMember(form);
              canvas.addMember(selectButton);
              canvas.draw();  
          }  
      
      class SomeDS extends RestDataSource {  
      
          public SomeDS() {  
      
              OperationBinding fetch = new OperationBinding();  
              fetch.setOperationType(DSOperationType.FETCH);  
              fetch.setDataProtocol(DSProtocol.POSTMESSAGE);
              setOperationBindings(fetch);
      
              setDataFormat(DSDataFormat.XML);
      
              DataSourceTextField nameField = new DataSourceTextField("name", "Item", 128, true);  
              DataSourceTextField idField = new DataSourceTextField("id", "ID", 10, true);  
              idField.setPrimaryKey(true);  
      
              setFields(nameField, idField);  
      
              setDataURL("ds.jsp");
          }  
      }
      Code:
      <%@ page import="org.apache.commons.io.IOUtils" %>
      <%@ page import="javax.xml.xpath.*" %>
      <%@ page import="org.xml.sax.*" %>
      <%@ page import="java.io.*" %>
      <response>
      <status>0</status>
      <%
              String data = IOUtils.toString(request.getInputStream(), "UTF8");
      
              XPathFactory xPathfactory = XPathFactory.newInstance();
              XPath xpath = xPathfactory.newXPath();
              XPathExpression expr = xpath.compile("/request/data/id");        
              String id = (String)expr.evaluate(new InputSource(new StringReader(data)));
              expr = xpath.compile("/request/startRow");        
              String startRow = (String)expr.evaluate(new InputSource(new StringReader(data)));
              expr = xpath.compile("/request/endRow");        
              String endRow = (String)expr.evaluate(new InputSource(new StringReader(data)));
      
              int start = 1;
              int end = 80;
              int totalRows = 1000;
      
              if (!id.isEmpty()) 
                  start = end = Integer.parseInt(id);
      
              if (!startRow.isEmpty()) {
                  start = Integer.parseInt(startRow);
                  end = Integer.parseInt(endRow);
              }
      
              out.println("<startRow>" + start + "</startRow>");
              out.println("<endRow>" + end + "</endRow>");
              out.println("<totalRows>" + totalRows + "</totalRows>");
              out.println("<data>");
      
              for(int i = start; i < end + 1; i++) 
                  out.println("<record><id>" + i + "</id><name>name" + i + "</name></record>");
      %>            
      </data>
      </response>

      Comment


        #4
        This one might be related.

        Best regards
        Blama

        Comment


          #5
          Not a correct expectation. If the selected item happened to be 1 millionth in the list, would you expect us to select all 1 million records? Obviously not. The selection we show accurately reflects what will be chosen if you take the current completion.

          Comment


            #6
            Well, the application should be designed so that the user is able to drop down any combo box and select an item near the end, and if so, the framework should also be able to reasonably do the same.
            With 1 million records it is unusable for the user so it is obviously an incorrect counter example.
            However, I see your point, it might just isn't worth to fetch all the data needed.

            Comment


              #7
              The user can already scroll to the bottom of the list, if needed, to see the last rows without loading all the intervening data.

              Note also that the other major flaw with your proposed behavior is needing to find the index of the record in the whole dataset before that range could be loaded. This is not only a potentially expensive operation, but not all datastores can do it..

              So again, current behavior is correct, nothing to change here.

              Comment

              Working...
              X