Announcement

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

    Easy problem with setting value to non-Databound SelectItem with valueMap

    Hi Isomorphic,

    I have following problem with programmatically setting a date value to a non-Databound SelectItem with a valueMap (using v10.1p_2017-02-22).
    No way I try I get the wanted result. For one of the cases I expect the following:
    • Click "Set value".
    • The correct value is selected from the valueMap (Q3/2017)
    • Click "Save"
    • Save succeeds.
    • After window close/reopen: The correct value is selected from the valueMap and the SelectItem has exactly 4 entries (not 5)
    On load, I always get a fifth entry named "09/30/2017" in the SelectItem (if I set the value to this date before via the 1st "Set value" + 1st "Save").
    Also for the lower two SelectItems, where the "Set value" works as expected, I get "Must be a date" as validation error for "Save".

    BuiltInDS.java:
    Code:
    package com.smartgwt.sample.client;
    
    import java.util.Date;
    import java.util.LinkedHashMap;
    
    import com.google.gwt.core.client.EntryPoint;
    import com.smartgwt.client.Version;
    import com.smartgwt.client.core.KeyIdentifier;
    import com.smartgwt.client.data.AdvancedCriteria;
    import com.smartgwt.client.data.DataSource;
    import com.smartgwt.client.types.OperatorId;
    import com.smartgwt.client.util.Page;
    import com.smartgwt.client.util.PageKeyHandler;
    import com.smartgwt.client.util.SC;
    import com.smartgwt.client.widgets.IButton;
    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.form.DynamicForm;
    import com.smartgwt.client.widgets.form.fields.FormItem;
    import com.smartgwt.client.widgets.form.fields.SelectItem;
    import com.smartgwt.client.widgets.grid.ListGrid;
    import com.smartgwt.client.widgets.layout.VLayout;
    
    public class BuiltInDS implements EntryPoint {
        private VLayout mainLayout;
        private IButton recreateBtn;
    
        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();
                }
            });
    
            mainLayout = new VLayout(20);
            mainLayout.setWidth100();
            mainLayout.setHeight100();
    
            recreateBtn = new IButton("Recreate");
            recreateBtn.addClickHandler(new ClickHandler() {
                @Override
                public void onClick(ClickEvent event) {
                    recreate();
                }
            });
            mainLayout.addMember(recreateBtn);
            recreate();
            mainLayout.draw();
        }
    
        private void recreate() {
            Window w = new Window();
            w.setWidth("95%");
            w.setHeight("95%");
            w.setMembersMargin(0);
            w.setModalMaskOpacity(70);
            w.setTitle(" (" + Version.getVersion() + "/" + Version.getSCVersionNumber() + ")");
            w.setTitle("SelectItem valueMap and setValue() problems" + w.getTitle());
            w.setShowMinimizeButton(false);
            w.setIsModal(true);
            w.setShowModalMask(true);
            w.setAutoDraw(false);
            w.centerInPage();
    
            w.addItem(getFormLayout(true, true));
            w.addItem(getFormLayout(true, false));
            w.addItem(getFormLayout(false, true));
            w.addItem(getFormLayout(false, false));
    
            ListGrid lg = new ListGrid(DataSource.get("supplyItem"));
            lg.setCanEdit(true);
            lg.fetchData(new AdvancedCriteria("itemID", OperatorId.EQUALS, 1484));
            w.addItem(lg);
    
            w.show();
        }
    
        private VLayout getFormLayout(final boolean setAsId, final boolean useStringMap) {
            VLayout vL = new VLayout(5);
    
            final DynamicForm df = new DynamicForm();
            df.setDataSource(DataSource.get("supplyItem"));
            final FormItem sku = new FormItem("SKU");
            final FormItem nextShipment = new SelectItem("nextShipment");
            if (useStringMap)
                nextShipment.setValueMap(getStringValueMap());
            else
                nextShipment.setValueMap(getDateValueMap());
    
            df.setFields(sku, nextShipment);
            vL.addMember(df);
            df.fetchData(new AdvancedCriteria("itemID", OperatorId.EQUALS, 1484));
    
            IButton set = new IButton("Set value", new ClickHandler() {
                @SuppressWarnings("deprecation")
                @Override
                public void onClick(ClickEvent event) {
                    if (setAsId)
                        nextShipment.setValue(new Date(117, 8, 30));
                    else
                        nextShipment.setValue("Q3/2017");
                }
            });
            vL.addMember(set);
    
            IButton save = new IButton("Save", new ClickHandler() {
                @Override
                public void onClick(ClickEvent event) {
                    df.saveData();
                }
            });
            vL.addMember(save);
    
            return vL;
        }
    
        private LinkedHashMap<String, String> getStringValueMap() {
            LinkedHashMap<String, String> vm = new LinkedHashMap<String, String>();
            vm.put("03/31/2017", "Q1/2017");
            vm.put("06/30/2017", "Q2/2017");
            vm.put("09/30/2017", "Q3/2017");
            vm.put("12/31/2017", "Q4/2017");
            return vm;
        }
    
        @SuppressWarnings("deprecation")
        private LinkedHashMap<Date, String> getDateValueMap() {
            LinkedHashMap<Date, String> vm = new LinkedHashMap<Date, String>();
            vm.put(new Date(117, 2, 31), "Q1/2017");
            vm.put(new Date(117, 5, 30), "Q2/2017");
            vm.put(new Date(117, 8, 30), "Q3/2017");
            vm.put(new Date(117, 11, 31), "Q4/2017");
            return vm;
        }
    }
    Thanks you and Best regards
    Blama
    Last edited by Blama; 22 Feb 2017, 10:26. Reason: Added "date" in the problem description.

    #2
    Hi Isomorphic,

    after seeing the format you use for dates when sending requests in the Developer Console's RPC Tab, I also tried with this valueMap, but had the same problem:
    Code:
        private LinkedHashMap<String, String> getUTCValueMap() {
            LinkedHashMap<String, String> vm = new LinkedHashMap<String, String>();
            vm.put("2017-03-31", "Q1/2017");
            vm.put("2017-06-30", "Q2/2017");
            vm.put("2017-09-30", "Q3/2017");
            vm.put("2017-12-31", "Q4/2017");
            return vm;
        }
    Please also note that the sentence
    Also for the lower two SelectItems, where the "Set value" works as expected, I get "Must be a date" as validation error for "Save".
    from the last post does not hold. Using the "Set value" button there, a fifth entry, that also says "Q3/2017", is added.

    Best regards
    Blama

    Comment


      #3
      It's not currently possible to have a Date-valued simple valueMap. One alternate way to do this is an optionDataSource with a date-valued valueField. The optionDataSource can be client-only.

      Comment


        #4
        Hi Isomorphic,

        thanks for the fast answer. I'll try that.
        The limitation with the String-only valueMap should really be mentioned in the setValueMap()-docs, possibly with the notion of the suggested workaround.

        Best regards
        Blama
        Last edited by Blama; 23 Feb 2017, 00:48. Reason: issue -> limitation

        Comment


          #5
          Hi Isomorphic,

          I did as suggested, please see the new code below.
          Problem is still the same (5th value in the SelectItem). Also, I get four warnings on startup, which all should not be there IMHO.

          Code:
          [B]1st two are [URL="http://forums.smartclient.com/forum/smart-gwt-technical-q-a/243009-wrong-warning-for-datasource-setcachedata-when-used-with-record"]this report[/URL]:[/B]
          12:13:57.038:MUP2:WARN:Log:setCacheData(): DataSource cache data is expected to be an array of ListGridRecords. This allows the data to be displayed as expected in ListGrids bound to this dataSource.
          12:13:57.202:MUP2:WARN:Log:setCacheData(): DataSource cache data is expected to be an array of ListGridRecords. This allows the data to be displayed as expected in ListGrids bound to this dataSource.
          [B]These two are most likely related to the issue itself:[/B]
          12:13:58.131:TMR0:WARN:fetchMissingValues:isc_SelectItem_9[nextShipment]:FetchMissingValues - filterLocally is false yet optionDataSource fetch included records that do not match our current data value. Ignoring these values.
          12:13:58.157:TMR1:WARN:fetchMissingValues:isc_SelectItem_11[nextShipment]:FetchMissingValues - filterLocally is false yet optionDataSource fetch included records that do not match our current data value. Ignoring these values.
          BuiltInDS.lava:
          Code:
          package com.smartgwt.sample.client;
          
          import java.util.ArrayList;
          import java.util.Date;
          
          import com.google.gwt.core.client.EntryPoint;
          import com.google.gwt.i18n.client.DateTimeFormat;
          import com.smartgwt.client.Version;
          import com.smartgwt.client.core.KeyIdentifier;
          import com.smartgwt.client.data.AdvancedCriteria;
          import com.smartgwt.client.data.DataSource;
          import com.smartgwt.client.data.DataSourceField;
          import com.smartgwt.client.data.Record;
          import com.smartgwt.client.types.FieldType;
          import com.smartgwt.client.types.OperatorId;
          import com.smartgwt.client.util.Page;
          import com.smartgwt.client.util.PageKeyHandler;
          import com.smartgwt.client.util.SC;
          import com.smartgwt.client.widgets.IButton;
          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.form.DynamicForm;
          import com.smartgwt.client.widgets.form.fields.FormItem;
          import com.smartgwt.client.widgets.form.fields.SelectItem;
          import com.smartgwt.client.widgets.grid.ListGrid;
          import com.smartgwt.client.widgets.layout.VLayout;
          
          public class BuiltInDS implements EntryPoint {
              private VLayout mainLayout;
              private IButton recreateBtn;
          
              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();
                      }
                  });
          
                  mainLayout = new VLayout(20);
                  mainLayout.setWidth100();
                  mainLayout.setHeight100();
          
                  recreateBtn = new IButton("Recreate");
                  recreateBtn.addClickHandler(new ClickHandler() {
                      @Override
                      public void onClick(ClickEvent event) {
                          recreate();
                      }
                  });
                  mainLayout.addMember(recreateBtn);
                  recreate();
                  mainLayout.draw();
              }
          
              private void recreate() {
                  Window w = new Window();
                  w.setWidth("95%");
                  w.setHeight("95%");
                  w.setMembersMargin(0);
                  w.setModalMaskOpacity(70);
                  w.setTitle(" (" + Version.getVersion() + "/" + Version.getSCVersionNumber() + ")");
                  w.setTitle("SelectItem valueMap and setValue() problems" + w.getTitle());
                  w.setShowMinimizeButton(false);
                  w.setIsModal(true);
                  w.setShowModalMask(true);
                  w.setAutoDraw(false);
                  w.centerInPage();
          
                  w.addItem(getFormLayout(true));
                  w.addItem(getFormLayout(false));
          
                  ListGrid lg = new ListGrid(DataSource.get("supplyItem"));
                  lg.setCanEdit(true);
                  lg.fetchData(new AdvancedCriteria("itemID", OperatorId.EQUALS, 1484));
                  w.addItem(lg);
          
                  w.show();
              }
          
              private VLayout getFormLayout(final boolean setAsId) {
                  VLayout vL = new VLayout(5);
          
                  final DynamicForm df = new DynamicForm();
                  df.setDataSource(DataSource.get("supplyItem"));
                  final FormItem sku = new FormItem("SKU");
                  final FormItem nextShipment = new SelectItem("nextShipment");
                  nextShipment.setOptionDataSource(getClientDataSource());
                  nextShipment.setDisplayField("displayField");
                  nextShipment.setValueField("valueField");
          
                  df.setFields(sku, nextShipment);
                  vL.addMember(df);
                  df.fetchData(new AdvancedCriteria("itemID", OperatorId.EQUALS, 1484));
          
                  IButton set = new IButton("Set value", new ClickHandler() {
                      @SuppressWarnings("deprecation")
                      @Override
                      public void onClick(ClickEvent event) {
                          if (setAsId)
                              nextShipment.setValue(new Date(117, 8, 30));
                          else
                              nextShipment.setValue("Q3/2017");
                      }
                  });
                  vL.addMember(set);
          
                  IButton save = new IButton("Save", new ClickHandler() {
                      @Override
                      public void onClick(ClickEvent event) {
                          df.saveData();
                      }
                  });
                  vL.addMember(save);
          
                  return vL;
              }
          
              private static DataSource getClientDataSource() {
                  final String VALUEFIELD = "valueField";
                  final String DISPLAYFIELD = "displayField";
          
                  DataSource ds = new DataSource();
                  ds.setClientOnly(true);
                  ds.setTitleField(DISPLAYFIELD);
                  DataSourceField valueField = new DataSourceField(VALUEFIELD, FieldType.DATE);
                  valueField.setPrimaryKey(true);
                  DataSourceField displayField = new DataSourceField(DISPLAYFIELD, FieldType.TEXT);
                  ds.setFields(valueField, displayField);
          
                  ArrayList<Record> recordList = new ArrayList<Record>();
                  DateTimeFormat dtf = DateTimeFormat.getFormat("yyyy-MM-dd");
          
                  {
                      Record r = new Record();
                      r.setAttribute(VALUEFIELD, dtf.parseStrict("2017-03-31"));
                      r.setAttribute(DISPLAYFIELD, "Q1/2017");
                      recordList.add(r);
                  }
                  {
                      Record r = new Record();
                      r.setAttribute(VALUEFIELD, dtf.parseStrict("2017-06-30"));
                      r.setAttribute(DISPLAYFIELD, "Q2/2017");
                      recordList.add(r);
                  }
                  {
                      Record r = new Record();
                      r.setAttribute(VALUEFIELD, dtf.parseStrict("2017-09-30"));
                      r.setAttribute(DISPLAYFIELD, "Q3/2017");
                      recordList.add(r);
                  }
                  {
                      Record r = new Record();
                      r.setAttribute(VALUEFIELD, dtf.parseStrict("2017-12-31"));
                      r.setAttribute(DISPLAYFIELD, "Q4/2017");
                      recordList.add(r);
                  }
                  ds.setCacheData(recordList.toArray(new Record[recordList.size()]));
                  return ds;
              }
          
          }
          Best regards
          Blama

          Comment


            #6
            I think if you compare the fetchMissingValueReply-fetch's criteria and the result, you can see the reason for the warning as well as for the issue:

            Request:
            Code:
            {
                dataSource:"isc_DataSource_8", 
                operationType:"fetch", 
                componentId:"isc_DynamicForm_8", 
                data:{
                    [B]valueField:"2017-09-30"[/B]
                }, 
                textMatchStyle:"exact", 
                callback:{
                    target:[SelectItem ID:isc_SelectItem_17 name:nextShipment], 
                    methodName:"fetchMissingValueReply"
                }, 
                ...
            Response:
            Code:
            [
                {
                    [B]valueField:"2017-09-29T22:00:00.000", [/B]
                    displayField:"Q3/2017"
                }
            ]
            Best regards
            Blama

            Comment


              #7
              Since the field is type "date" you should use DateUtil.createLogicalDate() to create the values for the field. What you've done here is effectively put values that are valid for a "datetime" field into the DataSource data.

              Comment


                #8
                Hi Isomorphic,

                it is working now with the display of the correct value, thanks a lot. Actually I saw LogicalValue before in the docs and remembered the name, but in Eclipse it has no accessible constructor (which is OK) and the docs do not point to DateUtil.

                I do still have a small problem with my sample, though. See this revised and warning-free testcase:
                Code:
                package com.smartgwt.sample.client;
                
                import java.util.ArrayList;
                
                import com.google.gwt.core.client.EntryPoint;
                import com.smartgwt.client.Version;
                import com.smartgwt.client.core.KeyIdentifier;
                import com.smartgwt.client.data.AdvancedCriteria;
                import com.smartgwt.client.data.DataSource;
                import com.smartgwt.client.data.DataSourceField;
                import com.smartgwt.client.types.FieldType;
                import com.smartgwt.client.types.OperatorId;
                import com.smartgwt.client.util.DateUtil;
                import com.smartgwt.client.util.Page;
                import com.smartgwt.client.util.PageKeyHandler;
                import com.smartgwt.client.util.SC;
                import com.smartgwt.client.widgets.IButton;
                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.form.DynamicForm;
                import com.smartgwt.client.widgets.form.fields.FormItem;
                import com.smartgwt.client.widgets.form.fields.SelectItem;
                import com.smartgwt.client.widgets.grid.ListGrid;
                import com.smartgwt.client.widgets.grid.ListGridRecord;
                import com.smartgwt.client.widgets.layout.VLayout;
                
                public class BuiltInDS implements EntryPoint {
                    private VLayout mainLayout;
                    private IButton recreateBtn;
                
                    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();
                            }
                        });
                
                        mainLayout = new VLayout(20);
                        mainLayout.setWidth100();
                        mainLayout.setHeight100();
                
                        recreateBtn = new IButton("Recreate");
                        recreateBtn.addClickHandler(new ClickHandler() {
                            @Override
                            public void onClick(ClickEvent event) {
                                recreate();
                            }
                        });
                        mainLayout.addMember(recreateBtn);
                        recreate();
                        mainLayout.draw();
                    }
                
                    private void recreate() {
                        Window w = new Window();
                        w.setWidth("95%");
                        w.setHeight("95%");
                        w.setMembersMargin(0);
                        w.setModalMaskOpacity(70);
                        w.setTitle(" (" + Version.getVersion() + "/" + Version.getSCVersionNumber() + ")");
                        w.setTitle("SelectItem valueMap and setValue() problems" + w.getTitle());
                        w.setShowMinimizeButton(false);
                        w.setIsModal(true);
                        w.setShowModalMask(true);
                        w.setAutoDraw(false);
                        w.centerInPage();
                
                        w.addItem(getFormLayout());
                
                        ListGrid lg = new ListGrid(DataSource.get("supplyItem"));
                        lg.setCanEdit(true);
                        lg.fetchData(new AdvancedCriteria("itemID", OperatorId.EQUALS, 1484));
                        w.addItem(lg);
                
                        w.show();
                    }
                
                    private VLayout getFormLayout() {
                        VLayout vL = new VLayout(5);
                
                        final DynamicForm df = new DynamicForm();
                        df.setDataSource(DataSource.get("supplyItem"));
                        final FormItem sku = new FormItem("SKU");
                        final FormItem nextShipment = new SelectItem("nextShipment");
                        nextShipment.setOptionDataSource(getClientDataSource());
                        nextShipment.setDisplayField("displayField");
                        nextShipment.setValueField("valueField");
                        final FormItem units = new FormItem("units");
                
                        df.setFields(sku, nextShipment, units);
                        vL.addMember(df);
                        df.fetchData(new AdvancedCriteria("itemID", OperatorId.EQUALS, 1484));
                
                        IButton set = new IButton("Set value", new ClickHandler() {
                            @Override
                            public void onClick(ClickEvent event) {
                                nextShipment.setValue(DateUtil.createLogicalDate(2017, 5, 30));
                            }
                        });
                        vL.addMember(set);
                
                        IButton save = new IButton("Save", new ClickHandler() {
                            @Override
                            public void onClick(ClickEvent event) {
                                df.saveData();
                            }
                        });
                        vL.addMember(save);
                
                        return vL;
                    }
                
                    private static DataSource getClientDataSource() {
                        final String VALUEFIELD = "valueField";
                        final String DISPLAYFIELD = "displayField";
                
                        DataSource ds = new DataSource();
                        ds.setClientOnly(true);
                        ds.setTitleField(DISPLAYFIELD);
                        DataSourceField valueField = new DataSourceField(VALUEFIELD, FieldType.DATE);
                        valueField.setPrimaryKey(true);
                        DataSourceField displayField = new DataSourceField(DISPLAYFIELD, FieldType.TEXT);
                        ds.setFields(valueField, displayField);
                
                        ArrayList<ListGridRecord> recordList = new ArrayList<ListGridRecord>();
                        {
                            ListGridRecord r = new ListGridRecord();
                            r.setAttribute(VALUEFIELD, DateUtil.createLogicalDate(2017, 2, 31));
                            r.setAttribute(DISPLAYFIELD, "Q1/2017");
                            recordList.add(r);
                        }
                        {
                            ListGridRecord r = new ListGridRecord();
                            r.setAttribute(VALUEFIELD, DateUtil.createLogicalDate(2017, 5, 30));
                            r.setAttribute(DISPLAYFIELD, "Q2/2017");
                            recordList.add(r);
                        }
                        {
                            ListGridRecord r = new ListGridRecord();
                            r.setAttribute(VALUEFIELD, DateUtil.createLogicalDate(2017, 8, 30));
                            r.setAttribute(DISPLAYFIELD, "Q3/2017");
                            recordList.add(r);
                        }
                        {
                            ListGridRecord r = new ListGridRecord();
                            r.setAttribute(VALUEFIELD, DateUtil.createLogicalDate(2017, 11, 31));
                            r.setAttribute(DISPLAYFIELD, "Q4/2017");
                            recordList.add(r);
                        }
                        ds.setCacheData(recordList.toArray(new ListGridRecord[recordList.size()]));
                        return ds;
                    }
                }
                When you open the SelectItem for units, the current entry is highlighted. This is not the case for the nextShipment SelectItem.

                Best regards
                Blama

                Comment


                  #9
                  Hi Isomorphic,

                  could you reproduce the problem from #8?

                  Thank you & Best regards
                  Blama

                  Comment


                    #10
                    Apologies for the delay on this, amid the big push for the new Tahoe skin - we'll take a look today.

                    Comment


                      #11
                      This has been fixed for all field-types, in builds dated March 11 and later of all relevant versions.

                      Comment


                        #12
                        Hi Isomorphic,

                        the problem from #8 is fixed for my usecase in v10.1p_2017-03-11.

                        Thank you & Best regards
                        Blama

                        Comment


                          #13
                          Hi Isomorphic,

                          this should really be added, either in the docs or at least as warning in the Developer Console log.
                          Originally posted by Blama View Post
                          The limitation with the String-only valueMap should really be mentioned in the setValueMap()-docs, possibly with the notion of the suggested workaround.
                          Best regards
                          Blama

                          Comment


                            #14
                            Hi Isomorphic,

                            this is still easy to get wrong with the missing javadocs.

                            Best regards
                            Blama

                            Comment


                              #15
                              Hi Isomorphic,

                              I think this is touched a bit in getValueMap(), but not in setValueMap():
                              Code:
                              In a form, valueMaps are used for FormItem types that allow the user to pick from a limited set of values, such as a SelectItem. An item's valueMap can be either an Array of String values or a Map of stored String property names to Java Objects.
                              The hint on using a client-only DataSource is missing, though.

                              Best regards
                              Blama

                              Comment

                              Working...
                              X