Announcement

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

    Problem setting new value to a multiple SelectItem in it's ItemChangeHandler

    Hi Isomorphic,

    please see below testcase.
    Usecase is the following: I had a DynamicForm with a BooleanItem (for Reseller) and a SelectItem (for time dimension). Now I wanted to combine those two into one multiple-SelectItem in order to safe space.
    Allowed are either "reseller", "one-Time-Entry" or "reseller"+"one-Time-Entry". Time entries itself are mutually exclusive.

    This works just fine if "Reseller" is selected. It does not otherwise. Then it is possible to select many timeEntries.
    As you can see in the log, it should also work in that case. The value passed to setValue() is correct - it just does not correctly display the current value as it should afterwards.

    Am I doing everything correctly here (calling setValue in the ItemChangeHandler) and if so, what is going wrong here?
    I also created an easier testcase (also included), that shows that setValue() is working as expected.

    Tested with latest 5.1p and 6.1d (SNAPSHOT_v11.1d_2017-04-14).
    Code:
    package com.smartgwt.sample.client;
    
    import java.util.ArrayList;
    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.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.Label;
    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.events.ItemChangeEvent;
    import com.smartgwt.client.widgets.form.events.ItemChangeHandler;
    import com.smartgwt.client.widgets.form.fields.SelectItem;
    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("35%");
            w.setHeight("35%");
            w.setMembersMargin(0);
            w.setModalMaskOpacity(70);
            w.setTitle(" (" + Version.getVersion() + "/" + Version.getSCVersionNumber() + ")");
            w.setTitle("Works with reseller selected, but not without" + w.getTitle());
            w.setShowMinimizeButton(false);
            w.setIsModal(true);
            w.setShowModalMask(true);
            w.centerInPage();
            w.setCanDragResize(true);
    
            final DynamicForm groupByDynamicForm = new GroupByDynamicForm();
            w.addItem(groupByDynamicForm);
    
            Label l = new Label("Easier testcase below:");
            w.addItem(l);
    
            LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>();
            valueMap.put("year", "Year");
            valueMap.put("quarterAndYear", "Quarter");
            valueMap.put("monthAndYear", "Month");
            valueMap.put("RESELLER", "Reseller");
    
            final DynamicForm form2 = new DynamicForm();
    
            final SelectItem si = new SelectItem("GROUPINGOPTIONS2", "TEST2");
            si.setWidth(250);
            si.setValueMap(valueMap);
            si.setMultiple(true);
            form2.setFields(si);
            w.addItem(form2);
    
            IButton setOne = new IButton("Set year", new ClickHandler() {
                @Override
                public void onClick(ClickEvent event) {
                    String[] one = new String[1];
                    one[0] = "year";
                    si.setValue(one);
                }
            });
            w.addItem(setOne);
    
            IButton setTwo = new IButton("Set year+month", new ClickHandler() {
                @Override
                public void onClick(ClickEvent event) {
                    String[] two = new String[2];
                    two[0] = "year";
                    two[1] = "monthAndYear";
                    si.setValue(two);
                }
            });
            w.addItem(setTwo);
    
            w.show();
        }
    
        private final class GroupByDynamicForm extends DynamicForm {
            private ArrayList<String> toStringAL(Object[] objArray) {
                if (objArray == null)
                    return null;
    
                ArrayList<String> al = new ArrayList<String>(objArray.length);
                for (int i = 0; i < objArray.length; i++)
                    al.add(objArray[i].toString());
                return al;
            }
    
            private ArrayList<String> getNewGrouping(Object[] oldValues, Object[] newValues) {
                ArrayList<String> oV = toStringAL(oldValues);
                ArrayList<String> nV = toStringAL(newValues);
    
                // Change to 0, from 0, or de-selecting
                if (oV == null || nV == null || nV.size() < oV.size())
                    return nV;
    
                // Additionally selecting
                ArrayList<String> helper = new ArrayList<String>(nV);
                helper.removeAll(oV);
                String addedValue = helper.get(0);
    
                switch (addedValue) {
                case "RESELLER":
                case "USER":
                    break;
                case "year":
                    oV.remove("quarterAndYear");
                    oV.remove("monthAndYear");
                    break;
                case "quarterAndYear":
                    oV.remove("year");
                    oV.remove("monthAndYear");
                    break;
                case "monthAndYear":
                    oV.remove("year");
                    oV.remove("quarterAndYear");
                    break;
                }
                oV.add(addedValue);
                return oV;
            }
    
            public GroupByDynamicForm() {
                setNumCols(6);
    
                LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>();
                valueMap.put("year", "Year");
                valueMap.put("quarterAndYear", "Quarter");
                valueMap.put("monthAndYear", "Month");
                valueMap.put("RESELLER", "Reseller");
    
                SelectItem si = new SelectItem("GROUPINGOPTIONS", "Group by");
                si.setWidth(250);
                si.setValueMap(valueMap);
                si.setMultiple(true);
    
                addItemChangeHandler(new ItemChangeHandler() {
    
                    @Override
                    public void onItemChange(ItemChangeEvent event) {
    
                        ArrayList<String> newValueList = getNewGrouping((Object[]) event.getOldValue(), (Object[]) event.getNewValue());
                        if (newValueList != null && !newValueList.isEmpty()) {
                            event.cancel();
                            event.getItem().getForm().setValue("GROUPINGOPTIONS", newValueList.toArray(new String[newValueList.size()]));
                            SC.logWarn("Set  value: " + newValueList.toString());
                            if (event.getItem().getForm().getValue("GROUPINGOPTIONS") != null)
                                SC.logWarn("Read value: " + toStringAL((Object[]) event.getItem().getForm().getValue("GROUPINGOPTIONS")).toString());
                            event.getItem().getForm().markForRedraw("MFR");
                        } else {
                            event.getItem().clearValue();
                            SC.logWarn("New value: null");
                        }
                    }
                });
                setFields(si);
            }
        }
    }
    Thank you & Best regards
    Blama

    #2
    In this particular test case, the problem is that in the clearValue() case, you don't cancel() the change, so the change is still applied.

    Comment


      #3
      Hi Isomorphic,

      that's not it. But I'm very near to the root cause, which I suspect to be a framework issue. Please see this revised testcase and there "TEST3" and "TEST4", which are almost the same - the ItemChangeHandler cancels the event and sets the value to a fixed value.
      This works for TEST3, where a 2-value-array is set, but not for TEST4, where a 1-value array is set. In this case, the clicked option is still selected, even though the event was canceled.

      This is a great simplification of my usecase, but suffers from the same issue. It would be great if you could fix this one in 5.1p as well.

      Code:
      package com.smartgwt.sample.client;
      
      import java.util.ArrayList;
      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.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.Label;
      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.events.ItemChangeEvent;
      import com.smartgwt.client.widgets.form.events.ItemChangeHandler;
      import com.smartgwt.client.widgets.form.fields.SelectItem;
      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("35%");
              w.setHeight("35%");
              w.setMembersMargin(0);
              w.setModalMaskOpacity(70);
              w.setTitle(" (" + Version.getVersion() + "/" + Version.getSCVersionNumber() + ")");
              w.setTitle("Works with reseller selected, but not without" + w.getTitle());
              w.setShowMinimizeButton(false);
              w.setIsModal(true);
              w.setShowModalMask(true);
              w.centerInPage();
              w.setCanDragResize(true);
      
              LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>();
              valueMap.put("year", "Year");
              valueMap.put("quarterAndYear", "Quarter");
              valueMap.put("monthAndYear", "Month");
              valueMap.put("RESELLER", "Reseller");
      
              {
                  final DynamicForm groupByDynamicForm = new GroupByDynamicForm();
                  w.addItem(groupByDynamicForm);
              }
              {
                  Label l = new Label("Easier testcase below:");
                  w.addItem(l);
              }
              {
                  final DynamicForm form2 = new DynamicForm();
      
                  final SelectItem si = new SelectItem("GROUPINGOPTIONS2", "TEST2");
                  si.setWidth(250);
                  si.setValueMap(valueMap);
                  si.setMultiple(true);
                  form2.setFields(si);
                  w.addItem(form2);
      
                  IButton setOne = new IButton("Set year", new ClickHandler() {
                      @Override
                      public void onClick(ClickEvent event) {
                          String[] one = new String[1];
                          one[0] = "year";
                          si.setValue(one);
                      }
                  });
                  w.addItem(setOne);
      
                  IButton setTwo = new IButton("Set year+month", new ClickHandler() {
                      @Override
                      public void onClick(ClickEvent event) {
                          String[] two = new String[2];
                          two[0] = "year";
                          two[1] = "monthAndYear";
                          si.setValue(two);
                      }
                  });
                  w.addItem(setTwo);
              }
              {
                  final DynamicForm form3 = new DynamicForm();
                  final SelectItem si = new SelectItem("GROUPINGOPTIONS3", "TEST3");
                  si.setWidth(250);
                  si.setValueMap(valueMap);
                  si.setMultiple(true);
                  form3.setFields(si);
                  form3.addItemChangeHandler(new ItemChangeHandler() {
                      @Override
                      public void onItemChange(ItemChangeEvent event) {
                          event.cancel();
                          event.getItem().clearValue();
                          event.getItem().getForm().setValue("GROUPINGOPTIONS3", new String[] { "year", "monthAndYear" });
                      }
                  });
                  w.addItem(form3);
              }
              {
                  final DynamicForm form4 = new DynamicForm();
                  final SelectItem si = new SelectItem("GROUPINGOPTIONS4", "TEST4");
                  si.setWidth(250);
                  si.setValueMap(valueMap);
                  si.setMultiple(true);
                  form4.setFields(si);
                  form4.addItemChangeHandler(new ItemChangeHandler() {
                      @Override
                      public void onItemChange(ItemChangeEvent event) {
                          event.cancel();
                          event.getItem().clearValue();
                          event.getItem().getForm().setValue("GROUPINGOPTIONS4", new String[] { "monthAndYear" });
                      }
                  });
                  w.addItem(form4);
              }
      
              w.show();
          }
      
          private final class GroupByDynamicForm extends DynamicForm {
              private ArrayList<String> toStringAL(Object[] objArray) {
                  if (objArray == null)
                      return null;
      
                  ArrayList<String> al = new ArrayList<String>(objArray.length);
                  for (int i = 0; i < objArray.length; i++)
                      al.add(objArray[i].toString());
                  return al;
              }
      
              private ArrayList<String> getNewGrouping(Object[] oldValues, Object[] newValues) {
                  ArrayList<String> oV = toStringAL(oldValues);
                  ArrayList<String> nV = toStringAL(newValues);
      
                  // Change to 0, from 0, or de-selecting
                  if (oV == null || nV == null || nV.size() < oV.size())
                      return nV;
      
                  // Additionally selecting
                  ArrayList<String> helper = new ArrayList<String>(nV);
                  helper.removeAll(oV);
                  String addedValue = helper.get(0);
      
                  switch (addedValue) {
                  case "RESELLER":
                      oV.remove("USER");
                      break;
                  case "USER":
                      oV.remove("RESELLER");
                      break;
                  case "year":
                      oV.remove("quarterAndYear");
                      oV.remove("monthAndYear");
                      break;
                  case "quarterAndYear":
                      oV.remove("year");
                      oV.remove("monthAndYear");
                      break;
                  case "monthAndYear":
                      oV.remove("year");
                      oV.remove("quarterAndYear");
                      break;
                  }
                  oV.add(addedValue);
                  return oV;
              }
      
              public GroupByDynamicForm() {
                  setNumCols(6);
      
                  LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>();
                  valueMap.put("year", "Year");
                  valueMap.put("quarterAndYear", "Quarter");
                  valueMap.put("monthAndYear", "Month");
                  valueMap.put("USER", "User");
                  valueMap.put("RESELLER", "Reseller");
      
                  SelectItem si = new SelectItem("GROUPINGOPTIONS", "Group by");
                  si.setWidth(250);
                  si.setValueMap(valueMap);
                  si.setMultiple(true);
      
                  addItemChangeHandler(new ItemChangeHandler() {
      
                      @Override
                      public void onItemChange(ItemChangeEvent event) {
      
                          ArrayList<String> newValueList = getNewGrouping((Object[]) event.getOldValue(), (Object[]) event.getNewValue());
                          if (newValueList != null && !newValueList.isEmpty()) {
                              event.cancel();
                              event.getItem().getForm().setValue("GROUPINGOPTIONS", newValueList.toArray(new String[newValueList.size()]));
                              SC.logWarn("Set value: " + newValueList.toString());
                              if (event.getItem().getForm().getValue("GROUPINGOPTIONS") != null)
                                  SC.logWarn("Read value: " + toStringAL((Object[]) event.getItem().getForm().getValue("GROUPINGOPTIONS")).toString());
                          } else {
                              event.cancel();
                              event.getItem().clearValue();
                              SC.logWarn("New value: null");
                          }
                      }
                  });
                  setFields(si);
              }
          }
      }
      Best regards
      Blama
      Last edited by Blama; 16 Apr 2017, 08:17.

      Comment


        #4
        This one's been fixed back to 5.0, for builds dated April 18 and later.

        Comment


          #5
          Hi Isomorphic,

          thanks a lot, I'll retest tomorrow and update here.

          Best regards
          Blama

          Comment


            #6


            Hi Isomorphic,

            testing SNAPSHOT_v11.1d_2017-04-18 the issue is gone, but I noticed another one, leading to temporary scrollbars.
            I can't reproduce the scrollbars in vanilla Tahoe, but the root cause.

            Please see this sample (I used GC57) and select "Giraffe" and "Cat" in that order. Then inspect. For me, it looks like this:

            Click image for larger version

Name:	Multi-Picklist.png
Views:	89
Size:	123.5 KB
ID:	244176

            As you can see, the height for the is 24px, for the rest it is 26 (with "px" and without, if that is an issue as well). For me in my Application (but not in the sample), this difference results in a lower-height row that then on hover shortly displays scrollbars.
            Also it is not clear to me when the style class is "pickListCell...." and when "tallPickListCell". It is not that selected cells are always "tallPickListCell", as you can see here.

            Best regards
            Blama

            Comment


              #7
              We don't see this issue - but that's because it was fixed this morning :)

              Please retest with tomorrow's build.

              Comment


                #8
                Hi Isomorphic,

                amazing. Will do. May I ask how you noticed the issue?

                Best regards
                Blama

                Comment


                  #9
                  Changes were made yesterday to properly enable the new LG.alternateRecord/FieldSuffix/Style stuff (which shades alternate rows and columns and their intersections) in conjunction with a new feature that enables us to show an unclipped glow around the selected row as a whole.

                  Those changes resulted in the tallCell style being used, which is unnecessary - we switched grids to use baseStyle:"cell" and no tallCellStyle - doing the same thing locally will fix it for you for today.

                  Comment


                    #10
                    Ah, ok, so you noticed during development in that area and not via some test.
                    Regarding the rollOverCanvas / .gridSelectionOver I just wanted to write you in a new thread.

                    Best regards
                    Blama

                    Comment

                    Working...
                    X