Announcement

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

    ComboBoxItem shows unintuitive error msg & removes entered value on validation error

    Hi Isomorphic,

    please see this testcase (using v10.0p_2015-05-13) and the attached screenshot:

    Code:
    package com.smartgwt.sample.client;
    
    import com.google.gwt.core.client.EntryPoint;
    import com.smartgwt.client.core.KeyIdentifier;
    import com.smartgwt.client.data.Criteria;
    import com.smartgwt.client.data.DataSource;
    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.events.ClickEvent;
    import com.smartgwt.client.widgets.events.ClickHandler;
    import com.smartgwt.client.widgets.form.DynamicForm;
    import com.smartgwt.client.widgets.form.fields.ComboBoxItem;
    import com.smartgwt.client.widgets.form.fields.TextItem;
    import com.smartgwt.client.widgets.layout.VLayout;
    
    public class BuiltInDS implements EntryPoint {
    	private VLayout vL;
    	private TestForm tF;
    
    	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();
    			}
    		});
    
    		vL = new VLayout(5);
    		vL.setPadding(20);
    		vL.setWidth100();
    		vL.setHeight100();
    		tF = new TestForm();
    
    		IButton validate = new IButton("Validate");
    		validate.addClickHandler(new ClickHandler() {
    			@Override
    			public void onClick(ClickEvent event) {
    				tF.validate();
    			}
    		});
    
    		IButton reload = new IButton("Reload");
    		reload.addClickHandler(new ClickHandler() {
    			@Override
    			public void onClick(ClickEvent event) {
    				vL.removeChild(tF);
    				tF.markForDestroy();
    				tF = new TestForm();
    				vL.addMember(tF, 0);
    			}
    		});
    		vL.addMembers(tF, validate, reload);
    		vL.draw();
    	}
    
    	private class TestForm extends DynamicForm {
    		public TestForm() {
    			super();
    			setDataSource(DataSource.get("employees"));
    			setAutoFetchData(false);
    
    			TextItem employeeId = new TextItem("EmployeeId");
    			TextItem name = new TextItem("Name");
    			ComboBoxItemEmployee reportsTo = new ComboBoxItemEmployee("ReportsTo");
    			TextItem job = new TextItem("Job");
    			TextItem email = new TextItem("Email");
    			setFields(employeeId, name, reportsTo, job, email);
    
    			fetchData(new Criteria("EmployeeId", "192"));
    		}
    	}
    
    	private class ComboBoxItemEmployee extends ComboBoxItem {
    		final private DataSource employeesDS = DataSource.get("employees");
    
    		public ComboBoxItemEmployee(String name) {
    			super(name);
    			setOptionDataSource(employeesDS);
    			setValueField(employeesDS.getPrimaryKeyFieldName());
    			setDisplayField("Name");
    			setSortField("Name");
    			setFetchMissingValues(true);
    			setValidateOnExit(true);
    			setBrowserSpellCheck(false);
    		}
    	}
    }
    I think that the validation error message should read something like "Please select an entry from the list" and that the entered value should not be removed (see screenshot).

    If you comment out setValidateOnExit(true), edit the ComboBoxItem to "Charles Madi", switch the field, and validate via the validate-button, the edited value is not removed, which is good. The error message is still unintuitive, tough.

    Best regards
    Blama
    Attached Files

    #2
    In practical terms, the way to resolve this issue is to call "setAddUnknownValues(false)" on your item.
    This will limit the user to selecting values from the list and automatically "completeOnTab".

    With addUnknownValues set to true (the default), when the user enters an unrecognized string (a partial value, or something else), the entered value will be stored as the value for the item when it is saved. This is as designed and allows support for the "URL-Bar" type pattern where the drop down list contains essentially "suggestions" but the user can enter values that don't match those suggestions.

    In your case the field value is supposed to be numeric, so the error message is correct - user has entered a non numeric value which can't be saved to the database. If they entered a numeric value we could store that as a new entry and there would be no validation error.

    Having said that the fact that the "Loading..." string gets stuck in the text box would appear to be a framework bug. We're looking into why that is happening and will likely get a fix in in the next day or two.

    Regards
    Isomorphic Software

    Comment


      #3
      We're actually having trouble reproducing the issue where the text field gets stuck containing the "Loading..." marker.

      Can you verify whether this is still happening for you with the attached test case with the latest nightly SmartGWT build?
      If so,
      - is it intermittent?
      - if so - how frequently does it occur for you (one in every 5 times? more? Less?) and what are the exact steps to reproduce?
      - is it browser-dependent for you? Which browser / OS?

      Thanks
      Isomorphic Software

      Comment


        #4
        Hi Isomorphic,

        first on the "Loading" matter (with unchanged testcase using current 5.1d now (I will retest with 5.0p, too), SNAPSHOT_v10.1d_2015-05-21):
        You are right, I have difficulties to reproduce every time and I'd say its less than 1 out of 10 in FF26, none so far in GC42 and 1 out of 2 in FF26 Dev Mode.
        I do see three requests for this action now:
        1. Start deployed sample in FF26
        2. Wait until loaded
        3. Click ComboBoxItem
        4. Crtl-A to select
        5. Enter fast "acb" + quickly tab

        Two of the requests are issues almost simultaneously (2nd before 1st returns):

        Request 1:
        Code:
        {
            dataSource:"employees", 
            operationType:"fetch", 
            componentId:"isc_BuiltInDS_TestForm_0", 
            data:{
                Name:"abc"
            }, 
            textMatchStyle:"exact", 
            callback:{
                target:[ComboBoxItem ID:isc_BuiltInDS_ComboBoxItemEmployee_1 name:ReportsTo], 
                methodName:"fetchMissingValueReply"
            }, 
            showPrompt:false, 
            oldValues:{
                Name:"abc"
            }, 
            requestId:"employees$6272", 
            internalClientContext:{
                newValue:"abc", 
                filterLocally:{
                }, 
                targetField:"Name", 
                fetchingMissingValues:{
                }
            }, 
            fallbackToEval:false, 
            componentContext:"ReportsTo", 
            lastClientEventThreadCode:"IFCS7", 
            bypassCache:true, 
            dataProtocol:"getParams"
        }
        Request 2:
        Code:
        {
            dataSource:"employees", 
            operationType:"fetch", 
            componentId:"isc_PickListMenu_0", 
            data:{
                Name:"abc"
            }, 
            startRow:0, 
            endRow:75, 
            sortBy:[
                "Name"
            ], 
            textMatchStyle:"startsWith", 
            resultSet:[ResultSet ID:isc_ResultSet_0 (dataSource: employees, created by: isc_PickListMenu_0)], 
            callback:{
                caller:[ResultSet ID:isc_ResultSet_0 (dataSource: employees, created by: isc_PickListMenu_0)], 
                methodName:"fetchRemoteDataReply"
            }, 
            willHandleError:true, 
            showPrompt:false, 
            prompt:"Finding Records that match your criteria...", 
            oldValues:{
                Name:"abc"
            }, 
            requestId:"employees$6273", 
            internalClientContext:{
                requestIndex:1
            }, 
            fallbackToEval:false, 
            lastClientEventThreadCode:"TMR0", 
            bypassCache:true, 
            dataProtocol:"getParams"
        }
        Request 3:
        Code:
        {
            dataSource:"employees", 
            operationType:"fetch", 
            componentId:"isc_BuiltInDS_TestForm_0", 
            data:{
                EmployeeId:"abc"
            }, 
            textMatchStyle:"exact", 
            callback:{
                target:[ComboBoxItem ID:isc_BuiltInDS_ComboBoxItemEmployee_1 name:ReportsTo], 
                methodName:"fetchMissingValueReply"
            }, 
            showPrompt:false, 
            oldValues:{
                EmployeeId:"abc"
            }, 
            requestId:"employees$6274", 
            internalClientContext:{
                newValue:"abc", 
                filterLocally:{
                }, 
                targetField:"EmployeeId", 
                fetchingMissingValues:{
                }
            }, 
            fallbackToEval:false, 
            componentContext:"ReportsTo", 
            lastClientEventThreadCode:"IBLR8", 
            bypassCache:true, 
            dataProtocol:"getParams"
        }
        Req1 + Req2 are most likely related to the issue you mentioned with the "use DS or OptionDS"-question. Again, this was now with 5.1d.

        I'll try with 5.0p now as well as give feedback to your correction of:
        Code:
        setAddUnknownValues(false);
        setPickListProperties(new ListGrid() {
        	{
        		setDataFetchMode(FetchMode.BASIC);
        	}
        });
        Unfortunately this does not work as expected.

        I hope you are OK with different replies for different tests.

        Best regards
        Blama

        Comment


          #5
          Hi Isomorphic,

          I retested now with same code and v10.0p_2015-05-21.
          The issue with the three requests also exists here, actually all three requests are fired before the 1st returns.

          I also succeeded in the "Loading"-message issue, although it behaves differently in FF26 and GC42/IE11 (all deployed):
          Steps to reproduce:
          1. Start sample
          2. Wait until data loaded
          3. Open "Charles Madigan" Dropdown with the mouse
          4. Select another entry
          5. Switch to "title"-field with the mouse
          6. Double click the last name in the dropdown to select the text
          7. hit "backspace" and directly after "tab" to leave the cell
          8. Result in FF26: "Loading" message and ComboBoxItem out of order
          9. Result in GC42/IE11: "Firstname " displayed and ComboBoxItem out of order


          By "ComboBoxItem out of order" I mean:
          • Does not react to text entry
          • Does not revalidate and remove exclamation mark when selecting entry from the dropdown
          • On click on "Validate" switches back to "Firstname "


          This happens in 100% of the tests.

          Best regards
          Blama

          Comment


            #6
            Hi Isomorphic,

            regarding the problem I mentioned with your correction of adding
            Code:
            setAddUnknownValues(false);
            setPickListProperties(new ListGrid() {
            	{
            		setDataFetchMode(FetchMode.BASIC);
            	}
            });
            to the sample (which works like a charm in the testcase!) I noticed that I might have an issue with my setPickListFilterCriteriaFunction() and that the framework is behaving like it should. I'll modify my code and retest tomorrow and reply if it does not work as expected.

            If you do have problems with the two previous posts please let me know.

            Best regards
            Blama

            Comment


              #7
              Hi Isomorphic,

              Originally posted by Blama View Post
              I'll modify my code and retest tomorrow and reply if it does not work as expected.
              I had a problem with my code. This setup of setPickListFilterCriteriaFunction() along with your changes gives me an advanced ComboBoxItem with respect to filtering that behaves like a default ComboBoxItem.

              Code:
              setAddUnknownValues(false);
              setPickListProperties(new ListGrid() {
              	{
              		setDataFetchMode(FetchMode.BASIC);
              	}
              });
              setPickListFilterCriteriaFunction(new FormItemCriteriaFunction() {
              	@Override
              	public Criteria getCriteria(FormItemFunctionContext itemContext) {
              		String enteredValue = ((ComboBoxItem) itemContext.getFormItem()).getEnteredValue();
              
              		if (itemContext.getFormItem().getValue() == null && (enteredValue == null || enteredValue.isEmpty())) {
              			SC.logWarn("Value is null, returning null");
              			return null;
              		}
              		if (!((ComboBoxItem) itemContext.getFormItem()).getFilterWithValue()) {
              			SC.logWarn("Not returning criteria, returning null");
              			return null;
              		} else {
              			SC.logWarn("Returning criteria for \"" + enteredValue + "\"");
              			return new AdvancedCriteria(OperatorId.OR, new Criterion[] { new Criterion("SHORTNAME", OperatorId.ISTARTS_WITH, enteredValue),
              					new Criterion("NAME", OperatorId.ICONTAINS, enteredValue) });
              		}
              	}
              });
              One question: In this setup it would be wrong to have setValidateOnExit(true), wouldn't it?
              It is unnecessary and for me, I think it introduces unwanted behaviour where I can have an unknown value, but with validation-exclamation mark.

              Best regards
              Blama

              Comment


                #8
                We would agree that using the valideOnExit setting here is a worse UI than the built-in behavior.

                Comment


                  #9
                  Hi Isomorphic,

                  can you reproduce the bug in post #5?
                  It is not important for me currently as I don't believe my users will edit that fast, but it would be great if it gets fixed eventually.

                  Best regards
                  Blama

                  Comment


                    #10
                    Hi,
                    "Loading.." bug is related to my previous post http://forums.smartclient.com/showthread.php?t=32917

                    Code:
                    //ComboBoxItem.js at handleEditorExit method:
                    
                                    // Otherwise, consider the value to be a display value. If we have an ODS and
                                    // display field, check whether we have a data value for it. If not, try to fetch
                                    // a data value for this display value using _checkForValueFieldValue().
                                    } else if (ods != null && displayField != null
                                               && elementValue != null && elementValue != "" &&
                                               this.shouldFetchMissingDisplayValue(elementValue)
                                              )
                                    {
                                        this._checkForValueFieldValue(value); // <- Here must be an elementValue not a value.
                                    }
                    that function `_checkForValueFieldValue(value)` will send with criteria { "displayFieldName" : "value" } instead of { "displayFieldName" : "elementValue"} and server is getting criteria {"displayFieldName" : 12345} if inputvalue maps and error occurs. In that case all combobox is freezes and entered into loading state, and loading state is never set to false as server wont retuning any results.

                    With your case, I'm thinking that your server is also returning zero records with in your scenario (maybe not related with the code above) and loading state is not set to false. Need more investigation in your scenario to verify.

                    Comment

                    Working...
                    X