Announcement

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

    Enhancement / Best practice with clearing big DynamicForm with a ValuesManager

    Hi Isomorphic,

    I have a case where a top-SelectItem in a ValuesManager-managed DynamicForm decides what to display in the detailForms below.
    These forms are cleared on change of the top from. The problem is that I think that because of the ValueManager I'm not allowed to use detailForms.clearValues().
    But I don't want to use myVM.clearValues().

    When using detailForms.clearValues() I get a problem with myVM.valuesHaveChanged(), that I need as well.

    Please see this v10.1p_2016-07-08 based testcase, that illustrates the problem (buttons shows false even after change).

    BuiltInDS.java:
    Code:
    package com.smartgwt.sample.client;
    
    import com.google.gwt.core.client.EntryPoint;
    import com.smartgwt.client.Version;
    import com.smartgwt.client.core.KeyIdentifier;
    import com.smartgwt.client.data.DataSource;
    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.ValuesManager;
    import com.smartgwt.client.widgets.form.fields.SelectItem;
    import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
    import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
    import com.smartgwt.client.widgets.grid.ListGridField;
    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.setWidth(200);
            recreateBtn.addClickHandler(new ClickHandler() {
                @Override
                public void onClick(ClickEvent event) {
                    recreate(true);
                }
            });
    
            mainLayout.addMembers(recreateBtn);
            mainLayout.draw();
        }
    
        private void recreate(boolean allowEmptyValue) {
            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-change does not shown by ValuesManager" + w.getTitle());
            w.setShowMinimizeButton(false);
            w.setIsModal(true);
            w.setShowModalMask(true);
            w.centerInPage();
    
            final ValuesManager vM = new ValuesManager();
    
            final DynamicForm invisibleDF = new DynamicForm();
            invisibleDF.setWidth(250);
            invisibleDF.setIsGroup(true);
    
            DynamicForm selectEmp = new DynamicForm();
            selectEmp.setWidth(250);
            selectEmp.setIsGroup(true);
            selectEmp.setValuesManager(vM);
    
            SelectItem employeeSI = new EmployeeSI("EmployeeId", allowEmptyValue);
            employeeSI.addChangedHandler(new ChangedHandler() {
                @Override
                public void onChanged(ChangedEvent event) {
                    invisibleDF.clearValues();
                    // Configure invisibleDF fields (MANY FIELDS)
                    // Add invisibleDF to main layout if not done already
                }
            });
    
            selectEmp.setFields(employeeSI);
    
            invisibleDF.setValuesManager(vM);
    
            IButton checkChanges = new IButton("Check Changes");
            checkChanges.addClickHandler(new ClickHandler() {
                @Override
                public void onClick(ClickEvent event) {
                    SC.say(vM.valuesHaveChanged().toString());
                }
            });
    
            w.addItem(selectEmp);
            w.addItem(checkChanges);
            w.show();
        }
    
        private class ListGridFieldHidden extends ListGridField {
            public ListGridFieldHidden(String name) {
                super(name);
                setHidden(true);
            }
        }
    
        private class EmployeeSI extends SelectItem {
            public EmployeeSI(String name, boolean allowEmptyValue) {
                super(name);
                setTitle("Employee");
                setOptionDataSource(DataSource.get("employees"));
                setValueField("EmployeeId");
                setDisplayField("Name");
                setSortField("Name");
    
                setRequired(true);
                setValidateOnChange(true);
    
                ListGridField empname = new ListGridField("Name");
                ListGridFieldHidden EmployeeId = new ListGridFieldHidden("EmployeeId");
                ListGridFieldHidden EmployeeType = new ListGridFieldHidden("EmployeeType");
                ListGridField Gender = new ListGridField("Gender");
    
                setPickListFields(EmployeeId, empname, EmployeeType, Gender);
            }
        }
    }
    How to solve this best?
    I could clear the form by listing the fields one by one in clearValue(java.lang.String fieldName), but I'd like it better if I could use the code as-is.
    Or could you create a new overload clearValues(DynamicForm formToClear) in ValuesManager?

    Another enhancement:
    Could add warnings in DynamicForm with a ValuesManager if APIs are used that should not be used in this case?

    Thank you & Best regards
    Blama

    #2
    The problem here is that form.setValuesManager(vM) is not the same as vM.addMember(form).

    Please try the latter, and you should find things work as you expect - if not, let us know.

    In the meantime, we'll make a note to do something about form.setValuesManager(), via either a doc change or an API update.

    Comment


      #3
      Hi Isomorphic,

      thanks for the fast answer. Does this mean that one should always use vM.addMember(form) instead of form.setValuesManager(vM)?
      Or even both?

      Best regards
      Blama

      Comment


        #4
        VM.addMember() does some important internal work, around managing the dataSource of the new member, and correctly binding and storing it's values.

        That needs to happen so, for now, yes - you should use addMember() - most likely, we'll enhance the DF.setValuesManager() codepath to achieve the same targets as VM.addMember().

        Comment


          #5
          OK, I will try that and let you know how it worked out.

          FYI, reading the docs, I saw that vM.addMember(form) says:
          Add a new member to this valuesManager. Any Canvas can be a member of a valuesManager, even components like Layout or TabSet that do not actually have any values to manage. When "valueless" components like these bind to a ValuesManager, it is in order to provide their own child components with a shared valuesManager so that complex data can be displayed and edited - see DataPath for more details.
          but there is no overload taking anything other than a DynamicForm in 5.1 (or even 6.1d).

          Best regards
          Blama

          Comment


            #6
            Note that, in addition to the things we already mentioned, VM.addMember() also sets up some internal observation of member value validation - since DF.setValuesManager() is just a generated setter for a public attribute, none of that work takes place in current versions. We'll update when the situation has been rectified.

            On your latter comment, we'll look at whether this is an incorrect doc, or a feature missing from SmartGWT and update here on that matter also.

            Comment


              #7
              We've added some APIs to deal with these reports - these will be available in builds of 5.1+ as of July 17.

              DF.setValuesManager() is now functionally equivalent to VM.addMember() - any of these calls will now achieve the same thing:

              Code:
              DF.setValuesManager(ValuesManager vm)
              DF.setValuesManager(String vmID)
              
              VM.addMember(DynamicForm member)
              VM.addMember(Canvas member)
              VM.addMember(String memberID)

              Comment


                #8
                Hi Isomorphic,

                using the very same testcase and latest v10.1p_2016-07-18, I get this exception in FF26 Dev Mode:
                [ERROR] [builtinds] - Uncaught exception escaped
                com.google.gwt.event.shared.UmbrellaException: Exception caught: Cannot cast com.smartgwt.client.widgets.form.DynamicForm to com.smartgwt.client.core.BaseClass
                Switching to VM.addMember(DynamicForm member) seems to work, though.
                Also, the online showcase sample (using 6.0p) does not show this error.

                Best regards
                Blama

                Comment


                  #9
                  Regarding the original report:
                  In #5 I wrote that I'll try the change in my application. I switched all usages to VM.addMember(DynamicForm member) and it seems to work here as well.

                  Thank you & Best regards
                  Blama

                  Comment


                    #10
                    This cast exception is addressed for tomorrow's builds.

                    Comment


                      #11
                      Hi Isomorphic,

                      I can confirm that the cast exception is gone using v10.1p_2016-07-19.

                      Best regards
                      Blama

                      Comment

                      Working...
                      X