Announcement

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

    FormItem objects not rendering according to underlying data type in SearchForm

    [SmartClient Version: v11.0p_2016-09-09/PowerEdition Deployment (built 2016-09-09) and also SmartClient Version: v11.0p_2016-09-28/PowerEdition Deployment (built 2016-09-28)]

    Some of our code has stopped working when we recently updated from SmartGWT 5.1 to 6.0. The cause seems to be a change in FormItem, although the problem can only be observed when FormItems are created within SearchForms.

    Prior to v6.0, the FormItem constructor looked like this:

    Code:
      public FormItem(String name) {
        setName(name);
      }
    ...and now in v6.0 it looks like this:

    Code:
      public FormItem(String name) {
        setName(name);
        setAttribute("editorType", "FormItem");
        linkToInstanceUponCreate();
      }
    What I am questioning here is the editorType attribute being explicitly set to FormItem. If I modify the Component XML in the Hello World (http://www.smartclient.com/#helloWorld)example to the following, you will see that the item in question is rendered as static text rather than as an editable item (in this case I would expect a TextItem).

    Code:
    <SearchForm
        autoFocus="true"
        numCols="3"
    ><items>
    
        <FormItem
            editorType="FormItem"
            type="text"
            name="you"
            title="Enter your name"
            selectOnFocus="true"
            wrapTitle="false"
            defaultValue="my friend"
            />
    
    </items></SearchForm>
    Now, if we change from containing our field within a SearchForm to a DynamicForm and try again the item renders correctly as a TextItem.. It also works if we keep the top-level container as a SearchForm but remove the editorType attribute.

    Similarly, if I modify our code to create a TextItem then the search field renders as expected. However, we cannot guarantee that all search fields we will be creating in this SearchForm will be TextItems and we would rather defer to the underlying logic that is already in place in the libraries to render an appropriate edit control based on the underlying type of the field. In other words, we'd rather create Formitem objects and have the SmartClient logic handle rendering of the appropriate controls based on the underlying type of the field definition in the datasource to which the SearchForm is bound.

    Regards,
    Gary
    Last edited by godonnell_ip; 28 Sep 2016, 15:39.

    #2
    It's invalid for you to set editorType to "FormItem" as that would be specifying what is basically an abstract class in a context where a concrete class is expected. Remove that setting and you'll get what you're expecting.

    Comment


      #3
      Thanks for the quick response.

      I agree it's invalid, and yet the example I posted above is only representative of what is happening in the larger context of our application. You will see from the v11.0 FormItem constructor that the editorType is explicitly being set to FormItem when my FormItem object is being instantiated. So, the example I supplied is simply intended to demonstrate the negative effect of doing this.

      If it helps, here's a screenshot of what I see in the Chrome debugger immediately after the FormItem object is instantiated. You will see that without any intervention on my part, the object that was created has editorType="FormItem" (the item was actually instantiated on line 2199 in the screenshot):



      However, when I do the same against the v10.1 libraries, this is not the case:



      Last edited by godonnell_ip; 28 Sep 2016, 15:45.

      Comment


        #4
        Yes - but so far you haven't demonstrated a negative consequence for any valid usage, and that editorType setting you see is part of a bugfix, so obviously, we're not going to reverse it for an invalid use case.

        Let us know if you can show a valid use case that has been affected.

        Comment


          #5
          OK - here's the use case:

          We have extended the base ListGrid to have substantially modified behavior. Part of this behavior includes the ability to specify within datasource definitions which fields that are to be used as s"quick search" fields for that datasource. This results in our IpListGridEditor rendering a SearchForm above the grid. This form contains a SelectItem in which the "quick search" field titles are contained in a ValueMap. This allows the user to quickly select which field they wish to search by.

          When the user selects a value from that SelectItem, we create a FormItem control that corresponds to the field they selected. This should be an editable control in which they can enter a value prior to clicking "Search". Naturally, we build appropriate filter criteria based on this value before fetching data. It is this edit control that is failing to render properly because of the assignment of editorType="FormItem".

          As I demonstrate in the above screenshots, this assignment occurs without any intervention from our code.

          This screencast may provide additional explanation: http://screencast.com/t/RSqiEXgp. The first part shows the application running after being compiled against v10.1, whereas from 00:26 you can see it running after compiling against v11.0. In the latter part of the video you can see that I am unable to enter values in the search field.

          Also, as mentioned in my original post, this does not present itself as a problem within DynamicForm containers, but only within SearchForm containers. Therefore, whether you should or should not reverse the change that has been made is less important to me than having the system behave in the manner in which it is intended. If that means that the SearchForm needs to be fixed, or another change needs to be changed elsewhere, then so be it. However, it seems as though the current behavior is incorrect.
          Last edited by godonnell_ip; 28 Sep 2016, 16:11.

          Comment


            #6
            So once again, setting editorType="FormItem" in Component XML is invalid. It was invalid before we made the change that affected you, and it's still invalid now.

            You haven't shown any instance of valid usage which is not behaving correctly, and that is of course the minimum requirement for a bug report (for any system) - that is, finding an actual bug!

            Let us know when you can show a minimal, ready-to-run test case where the framework is doing something wrong.

            Comment


              #7
              I think you are misunderstanding me. We are NOT setting editorType="FormItem" in our code. We are simply instantiating a FormItem object within a SearchForm container. This is all done in Java.

              Your code is setting the attribute in the FormItem constructor. The sample I described above that leverages ComponentXML is intended to represent the minimal use case you requested - it is the simplest method I have of demonstrating to you the effect of your code setting editorType when I do not anticipate that it would be set.
              Last edited by godonnell_ip; 28 Sep 2016, 17:40.

              Comment


                #8
                So far you have shown clearly incorrect usage and merely claimed there is some valid usage that is also affected.

                Instead, show the valid usage that was affected, as a test case.

                This, again, is not an unusual requirement. This is the most basic definition of what it means to file a valid bug. That's all we're looking for here - the usual.


                Comment


                  #9
                  OK - here's the test case you asked for, which is a two-line modification of builtinds along the lines I described above.

                  First, apply the change to the line marked MODIFICATION #1, which is to set the fields of boundForm to a new FormItem called "commonName". Build and run the application and click on "Animals". The field will render as an editable text field.

                  Now, apply the change to the line marked MODIFICATION #2, which is to change the type of boundForm to a SearchForm Build and run the application and click on "Animals". The field will render as a non-editable text field.

                  Stepping into FormItem within the Chrome debugger, you will see that the constructor specified an editorType of FormItem. If you compile this same code against v10.1, this property is not set during insantiation of the FormItem and the problem does not exhibit itself.

                  Code:
                  package com.smartgwt.sample.client;
                  
                  import com.google.gwt.core.client.EntryPoint;
                  import com.smartgwt.client.core.KeyIdentifier;
                  import com.smartgwt.client.data.DataSource;
                  import com.smartgwt.client.data.Record;
                  import com.smartgwt.client.types.SelectionStyle;
                  import com.smartgwt.client.types.SortArrow;
                  import com.smartgwt.client.util.PageKeyHandler;
                  import com.smartgwt.client.util.Page;
                  import com.smartgwt.client.util.SC;
                  import com.smartgwt.client.widgets.IButton;
                  import com.smartgwt.client.widgets.Label;
                  import com.smartgwt.client.widgets.events.ClickEvent;
                  import com.smartgwt.client.widgets.events.ClickHandler;
                  import com.smartgwt.client.widgets.form.DynamicForm;
                  import com.smartgwt.client.widgets.form.SearchForm;
                  import com.smartgwt.client.widgets.form.fields.FormItem;
                  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.grid.events.RecordClickEvent;
                  import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
                  import com.smartgwt.client.widgets.layout.HLayout;
                  import com.smartgwt.client.widgets.layout.VStack;
                  import com.smartgwt.client.widgets.viewer.DetailViewer;
                  
                  /**
                   * Entry point classes define <code>onModuleLoad()</code>.
                   */
                  public class BuiltInDS implements EntryPoint {
                      private ListGrid boundList;
                      private DynamicForm boundForm;            
                      private IButton saveBtn;
                      private DetailViewer boundViewer;
                      private IButton newBtn;
                  
                      /**
                       * This is the entry point method.
                       */
                      public void onModuleLoad() {
                          KeyIdentifier debugKey = new KeyIdentifier();
                          debugKey.setCtrlKey(true);
                          debugKey.setKeyName("D");
                  
                          Page.registerKey(debugKey, new PageKeyHandler() {
                              public void execute(String keyName) {
                                  SC.showConsole();
                              }
                          });
                  
                  
                          ListGrid grid = new ListGrid();
                          grid.setLeft(20);
                          grid.setTop(75);
                          grid.setWidth(130);
                          grid.setLeaveScrollbarGap(false);
                          grid.setShowSortArrow(SortArrow.NONE);
                          grid.setCanSort(false);
                          grid.setFields(new ListGridField("dsTitle", "Select a DataSource"));
                          grid.setData(new ListGridRecord[]{
                                  new DSRecord("Animals", "animals"),
                                  new DSRecord("Office Supplies", "supplyItem"),
                                  new DSRecord("Employees", "employees")}
                          );
                          grid.setSelectionType(SelectionStyle.SINGLE);
                          grid.addRecordClickHandler(new RecordClickHandler() {
                              public void onRecordClick(RecordClickEvent event) {
                                  DSRecord record = (DSRecord) event.getRecord();
                                  bindComponents(record.getDsName());
                              }
                          });
                  
                          grid.draw();
                  
                          VStack vStack = new VStack();
                          vStack.setLeft(175);
                          vStack.setTop(75);
                          vStack.setWidth("70%");
                          vStack.setMembersMargin(20);
                  
                          Label label = new Label();
                          label.setContents("<ul>" +
                                  "<li>select a datasource from the list at left to bind to these components</li>" +
                                  "<li>click a record in the grid to view and edit that record in the form</li>" +
                                  "<li>click <b>New</b> to start editing a new record in the form</li>" +
                                  "<li>click <b>Save</b> to save changes to a new or edited record in the form</li>" +
                                  "<li>click <b>Clear</b> to clear all fields in the form</li>" +
                                  "<li>click <b>Filter</b> to filter (substring match) the grid based on form values</li>" +
                                  "<li>click <b>Fetch</b> to fetch records (exact match) for the grid based on form values</li>" +
                                  "<li>double-click a record in the grid to edit inline (press Return, or arrow/tab to another record, to save)</li>" +
                                  "</ul>");
                          vStack.addMember(label);
                  
                          boundList = new ListGrid();
                          boundList.setHeight(200);
                          boundList.setCanEdit(true);
                  
                          boundList.addRecordClickHandler(new RecordClickHandler() {
                              public void onRecordClick(RecordClickEvent event) {
                                  Record record = event.getRecord();
                                  boundForm.editRecord(record);
                                  saveBtn.enable();
                                  boundViewer.viewSelectedData(boundList);
                              }
                          });
                          vStack.addMember(boundList);
                  
                          boundForm = new SearchForm();    // *** MODIFICATION #2
                          boundForm.setNumCols(6);
                          boundForm.setAutoFocus(false);
                          vStack.addMember(boundForm);
                  
                          HLayout hLayout = new HLayout(10);
                          hLayout.setMembersMargin(10);
                          hLayout.setHeight(22);
                  
                          saveBtn = new IButton("Save");
                          saveBtn.addClickHandler(new ClickHandler() {
                              public void onClick(ClickEvent event) {
                                  boundForm.saveData();
                                  if (!boundForm.hasErrors()) {
                                      boundForm.clearValues();
                                      saveBtn.disable();
                                  }
                              }
                          });
                          hLayout.addMember(saveBtn);
                  
                          newBtn = new IButton("New");
                          newBtn.addClickHandler(new ClickHandler() {
                              public void onClick(ClickEvent event) {
                                  boundForm.editNewRecord();
                                  saveBtn.enable();
                              }
                          });
                          hLayout.addMember(newBtn);
                  
                          IButton clearBtn = new IButton("Clear");
                          clearBtn.addClickHandler(new ClickHandler() {
                              public void onClick(ClickEvent event) {
                                  boundForm.clearValues();
                                  saveBtn.disable();
                              }
                          });
                          hLayout.addMember(clearBtn);
                  
                          IButton filterBtn = new IButton("Filter");
                          filterBtn.addClickHandler(new ClickHandler() {
                              public void onClick(ClickEvent event) {
                                  boundList.filterData(boundForm.getValuesAsCriteria());
                                  saveBtn.disable();
                              }
                          });
                          hLayout.addMember(filterBtn);
                  
                          IButton fetchBtn = new IButton("Fetch");
                          fetchBtn.addClickHandler(new ClickHandler() {
                              public void onClick(ClickEvent event) {
                                  boundList.fetchData(boundForm.getValuesAsCriteria());
                                  saveBtn.disable();
                              }
                          });
                          hLayout.addMember(fetchBtn);
                  
                          vStack.addMember(hLayout);
                  
                          boundViewer = new DetailViewer();
                          vStack.addMember(boundViewer);
                  
                          vStack.draw();
                      }
                  
                      private void bindComponents(String dsName) {
                          DataSource ds = DataSource.get(dsName);
                          boundList.setDataSource(ds);
                          boundViewer.setDataSource(ds);
                          boundForm.setDataSource(ds);
                          boundForm.setFields(new FormItem("commonName"));    // *** MODIFICATION #1
                          boundList.fetchData();
                          newBtn.enable();
                          saveBtn.disable();
                      }
                  }

                  Comment


                    #10
                    Thanks for the test case. This is under investigation and we'll let you know as soon as we have more information for you.

                    Regards
                    Isomorphic Software

                    Comment


                      #11
                      We've made a change to resolve this issue. Please try the next nightly build dated September 30 or above

                      Regards
                      Isomorphic Software

                      Comment


                        #12
                        Thank you. This does indeed solve the problem in the test case. I will try shortly in our application but would expect similar results.

                        I had hoped this fix may also resolve the issue reported in http://forums.smartclient.com/forum/...in-datasources, but I'm afraid it didn't, so I'll make a note in that thread.

                        Regards,
                        Gary

                        Comment


                          #13
                          [SmartClient Version: v11.0p_2016-10-07/PowerEdition Deployment (built 2016-09-09) and also SmartClient Version: v11.0p_2016-09-28/PowerEdition Deployment (built 2016-09-28)]

                          I'm pretty sure this is the same problem, just with a slightly different field definition, so I hope you don't mind if I tack this onto this existing thread.

                          While the prior use case is now satisfied, the SearchForm fails to render fields as SelectItems when they are defined as _type="text"_ and with a _valueMap_ defined as _SelectItems_.

                          To see this, modify the BuiltInDS sample as follows (very similar to the above example):
                          1. Apply the change to the line marked MODIFICATION #1, which is to set the fields of boundForm to a new FormItem called "status". Build and run the application and click on "Animals". The field will render as a Selectitem.
                          2. Apply the change to the line marked MODIFICATION #2, which is to change the type of boundForm to a SearchForm. Build and run the application and click on "Animals". The field will render as an editable text field.
                          If we add the editorType attribute to all such field definitions we can work around this. However, we have quite a number of such definitions and would rather not do that. In other words, it would be a relief if you agree that this is not expected behavior and change it to match the behavior of a DynamicForm.

                          Thanks,
                          Gary O'Donnell

                          Code:
                          package com.smartgwt.sample.client;
                          
                          import com.google.gwt.core.client.EntryPoint;
                          import com.smartgwt.client.core.KeyIdentifier;
                          import com.smartgwt.client.data.DataSource;
                          import com.smartgwt.client.data.Record;
                          import com.smartgwt.client.types.SelectionStyle;
                          import com.smartgwt.client.types.SortArrow;
                          import com.smartgwt.client.util.PageKeyHandler;
                          import com.smartgwt.client.util.Page;
                          import com.smartgwt.client.util.SC;
                          import com.smartgwt.client.widgets.IButton;
                          import com.smartgwt.client.widgets.Label;
                          import com.smartgwt.client.widgets.events.ClickEvent;
                          import com.smartgwt.client.widgets.events.ClickHandler;
                          import com.smartgwt.client.widgets.form.DynamicForm;
                          import com.smartgwt.client.widgets.form.SearchForm;
                          import com.smartgwt.client.widgets.form.fields.FormItem;
                          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.grid.events.RecordClickEvent;
                          import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
                          import com.smartgwt.client.widgets.layout.HLayout;
                          import com.smartgwt.client.widgets.layout.VStack;
                          import com.smartgwt.client.widgets.viewer.DetailViewer;
                          
                          /**
                           * Entry point classes define <code>onModuleLoad()</code>.
                           */
                          public class BuiltInDS implements EntryPoint {
                              private ListGrid boundList;
                              private DynamicForm boundForm;            
                              private IButton saveBtn;
                              private DetailViewer boundViewer;
                              private IButton newBtn;
                          
                              /**
                               * This is the entry point method.
                               */
                              public void onModuleLoad() {
                                  KeyIdentifier debugKey = new KeyIdentifier();
                                  debugKey.setCtrlKey(true);
                                  debugKey.setKeyName("D");
                          
                                  Page.registerKey(debugKey, new PageKeyHandler() {
                                      public void execute(String keyName) {
                                          SC.showConsole();
                                      }
                                  });
                          
                          
                                  ListGrid grid = new ListGrid();
                                  grid.setLeft(20);
                                  grid.setTop(75);
                                  grid.setWidth(130);
                                  grid.setLeaveScrollbarGap(false);
                                  grid.setShowSortArrow(SortArrow.NONE);
                                  grid.setCanSort(false);
                                  grid.setFields(new ListGridField("dsTitle", "Select a DataSource"));
                                  grid.setData(new ListGridRecord[]{
                                          new DSRecord("Animals", "animals"),
                                          new DSRecord("Office Supplies", "supplyItem"),
                                          new DSRecord("Employees", "employees")}
                                  );
                                  grid.setSelectionType(SelectionStyle.SINGLE);
                                  grid.addRecordClickHandler(new RecordClickHandler() {
                                      public void onRecordClick(RecordClickEvent event) {
                                          DSRecord record = (DSRecord) event.getRecord();
                                          bindComponents(record.getDsName());
                                      }
                                  });
                          
                                  grid.draw();
                          
                                  VStack vStack = new VStack();
                                  vStack.setLeft(175);
                                  vStack.setTop(75);
                                  vStack.setWidth("70%");
                                  vStack.setMembersMargin(20);
                          
                                  Label label = new Label();
                                  label.setContents("<ul>" +
                                          "<li>select a datasource from the list at left to bind to these components</li>" +
                                          "<li>click a record in the grid to view and edit that record in the form</li>" +
                                          "<li>click <b>New</b> to start editing a new record in the form</li>" +
                                          "<li>click <b>Save</b> to save changes to a new or edited record in the form</li>" +
                                          "<li>click <b>Clear</b> to clear all fields in the form</li>" +
                                          "<li>click <b>Filter</b> to filter (substring match) the grid based on form values</li>" +
                                          "<li>click <b>Fetch</b> to fetch records (exact match) for the grid based on form values</li>" +
                                          "<li>double-click a record in the grid to edit inline (press Return, or arrow/tab to another record, to save)</li>" +
                                          "</ul>");
                                  vStack.addMember(label);
                          
                                  boundList = new ListGrid();
                                  boundList.setHeight(200);
                                  boundList.setCanEdit(true);
                          
                                  boundList.addRecordClickHandler(new RecordClickHandler() {
                                      public void onRecordClick(RecordClickEvent event) {
                                          Record record = event.getRecord();
                                          boundForm.editRecord(record);
                                          saveBtn.enable();
                                          boundViewer.viewSelectedData(boundList);
                                      }
                                  });
                                  vStack.addMember(boundList);
                          
                                  boundForm = new SearchForm();    // *** MODIFICATION #2
                                  boundForm.setNumCols(6);
                                  boundForm.setAutoFocus(false);
                                  vStack.addMember(boundForm);
                          
                                  HLayout hLayout = new HLayout(10);
                                  hLayout.setMembersMargin(10);
                                  hLayout.setHeight(22);
                          
                                  saveBtn = new IButton("Save");
                                  saveBtn.addClickHandler(new ClickHandler() {
                                      public void onClick(ClickEvent event) {
                                          boundForm.saveData();
                                          if (!boundForm.hasErrors()) {
                                              boundForm.clearValues();
                                              saveBtn.disable();
                                          }
                                      }
                                  });
                                  hLayout.addMember(saveBtn);
                          
                                  newBtn = new IButton("New");
                                  newBtn.addClickHandler(new ClickHandler() {
                                      public void onClick(ClickEvent event) {
                                          boundForm.editNewRecord();
                                          saveBtn.enable();
                                      }
                                  });
                                  hLayout.addMember(newBtn);
                          
                                  IButton clearBtn = new IButton("Clear");
                                  clearBtn.addClickHandler(new ClickHandler() {
                                      public void onClick(ClickEvent event) {
                                          boundForm.clearValues();
                                          saveBtn.disable();
                                      }
                                  });
                                  hLayout.addMember(clearBtn);
                          
                                  IButton filterBtn = new IButton("Filter");
                                  filterBtn.addClickHandler(new ClickHandler() {
                                      public void onClick(ClickEvent event) {
                                          boundList.filterData(boundForm.getValuesAsCriteria());
                                          saveBtn.disable();
                                      }
                                  });
                                  hLayout.addMember(filterBtn);
                          
                                  IButton fetchBtn = new IButton("Fetch");
                                  fetchBtn.addClickHandler(new ClickHandler() {
                                      public void onClick(ClickEvent event) {
                                          boundList.fetchData(boundForm.getValuesAsCriteria());
                                          saveBtn.disable();
                                      }
                                  });
                                  hLayout.addMember(fetchBtn);
                          
                                  vStack.addMember(hLayout);
                          
                                  boundViewer = new DetailViewer();
                                  vStack.addMember(boundViewer);
                          
                                  vStack.draw();
                              }
                          
                              private void bindComponents(String dsName) {
                                  DataSource ds = DataSource.get(dsName);
                                  boundList.setDataSource(ds);
                                  boundViewer.setDataSource(ds);
                                  boundForm.setDataSource(ds);
                                  boundForm.setFields(new FormItem("status"));    // *** MODIFICATION #1
                                  boundList.fetchData();
                                  newBtn.enable();
                                  saveBtn.disable();
                              }
                          }
                          Last edited by godonnell_ip; 10 Oct 2016, 16:51.

                          Comment


                            #14
                            I just applied [SmartClient Version: v11.0p_2016-10-16/PowerEdition Deployment (built 2016-10-16)] and unfortunately this most recently reported issue still persists.

                            Regards,
                            Gary O'Donnell

                            Comment


                              #15
                              Hi, Sorry for the silence on this - it is under investigation (we see the problem and what is causing it, but are still looking at how best to address it)

                              We'll follow up when we have more information (and probably a fix) for you

                              Regards
                              Isomorphic Software

                              Comment

                              Working...
                              X