Announcement

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

    ComboBoxItem uses value instead of displayField text to form Criteria (startup only)

    Hi Isomorphic,

    please see this BuiltInDS-based testcase (v10.0p_2015-05-06):

    Code:
    package com.smartgwt.sample.client;
    
    import com.google.gwt.core.client.EntryPoint;
    import com.smartgwt.client.core.KeyIdentifier;
    import com.smartgwt.client.data.AdvancedCriteria;
    import com.smartgwt.client.data.Criteria;
    import com.smartgwt.client.data.Criterion;
    import com.smartgwt.client.data.DataSource;
    import com.smartgwt.client.types.OperatorId;
    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.FormItemCriteriaFunction;
    import com.smartgwt.client.widgets.form.fields.FormItemFunctionContext;
    import com.smartgwt.client.widgets.form.fields.TextItem;
    import com.smartgwt.client.widgets.grid.CellFormatter;
    import com.smartgwt.client.widgets.grid.ListGridField;
    import com.smartgwt.client.widgets.grid.ListGridRecord;
    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 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, 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());
    			setFetchMissingValues(true);
    			setPickListFilterCriteriaFunction(new FormItemCriteriaFunction() {
    				@Override
    				public Criteria getCriteria(FormItemFunctionContext itemContext) {
    					if (itemContext.getFormItem().getValue() == null)
    						return null;
    					return new AdvancedCriteria(OperatorId.OR, new Criterion[] {
    							new Criterion("Name", OperatorId.ISTARTS_WITH, itemContext.getFormItem().getValue().toString()),
    							new Criterion("Email", OperatorId.ICONTAINS, itemContext.getFormItem().getValue().toString()) });
    				}
    			});
    
    			ListGridField nameLGF = new ListGridField("Name");
    			nameLGF.setCellFormatter(new CellFormatter() {
    				@Override
    				public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
    					return ((value != null) ? value : "No name") + " ("
    							+ ((record.getAttribute("Email") != null) ? record.getAttribute("Email") : "No email") + ")";
    				}
    			});
    
    			ListGridField emailLGF = new ListGridField("Email");
    			emailLGF.setHidden(true);
    
    			setPickListFields(nameLGF, emailLGF);
    			setPickListHeaderHeight(0);
    			setDisplayField("Name");
    			setSortField("Name");
    			setValidateOnExit(true);
    			setBrowserSpellCheck(false);
    		}
    	}
    }
    If you open the ComboBoxItem-popup after load via the arrow on the right, the following request is issued:
    Code:
    {
        dataSource:"employees", 
        operationType:"fetch", 
        componentId:"isc_PickListMenu_0", 
        data:{
            operator:"or", 
            criteria:[
                {
                    fieldName:"Name", 
                    operator:"iStartsWith", 
                    value:"4"
                }, 
                {
                    fieldName:"Email", 
                    operator:"iContains", 
                    value:"4"
                }
            ]
        }, 
        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:{
            operator:"or", 
            criteria:[
                {
                    fieldName:"Name", 
                    operator:"iStartsWith", 
                    value:"4"
                }, 
                {
                    fieldName:"Email", 
                    operator:"iContains", 
                    value:"4"
                }
            ]
        }, 
        requestId:"employees$6272", 
        internalClientContext:{
            requestIndex:1
        }, 
        fallbackToEval:false, 
        lastClientEventThreadCode:"IFCS1", 
        bypassCache:true
    }
    As you can see, the value "4" is used. I'd expect the ComboBoxItem to use "Charles Madigen" instead (or even better no Criteria, see default behaviour when using no setPickListFilterCriteriaFunction() below). When you enter text (or even just remove the last "n" from "Madigen", the AdvancedCriteria(OR of two Criterion) are generated correctly:
    Code:
    {
        dataSource:"employees", 
        operationType:"fetch", 
        componentId:"isc_PickListMenu_0", 
        data:{
            operator:"or", 
            criteria:[
                {
                    fieldName:"Name", 
                    operator:"iStartsWith", 
                    value:"Charles Madige"
                }, 
                {
                    fieldName:"Email", 
                    operator:"iContains", 
                    value:"Charles Madige"
                }
            ]
        }, 
        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:{
            operator:"or", 
            criteria:[
                {
                    fieldName:"Name", 
                    operator:"iStartsWith", 
                    value:"Charles Madige"
                }, 
                {
                    fieldName:"Email", 
                    operator:"iContains", 
                    value:"Charles Madige"
                }
            ]
        }, 
        requestId:"employees$6274", 
        internalClientContext:{
            requestIndex:1
        }, 
        fallbackToEval:false, 
        lastClientEventThreadCode:"TMR7", 
        bypassCache:true
    }
    Also, when you remove the setPickListFilterCriteriaFunction() call, the Criteria are generated correctly:
    Request (+ second request for rows 75-150, not shown):
    Code:
    {
        dataSource:"employees", 
        operationType:"fetch", 
        componentId:"isc_PickListMenu_0", 
        data:{
        }, 
        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:{
        }, 
        requestId:"employees$6272", 
        internalClientContext:{
            requestIndex:1
        }, 
        fallbackToEval:false, 
        lastClientEventThreadCode:"IFCS4", 
        bypassCache:true
    }
    Best regards
    Blama

    #2
    You're just putting your criteria together wrongly - you want to be using getEnteredValue() or you will, as you've seen, end up passing values for the valueField as criteria.

    Comment


      #3
      Hi Isomorphic,

      thanks for the hint. I changed my code to:
      Code:
      setPickListFilterCriteriaFunction(new FormItemCriteriaFunction() {
      	@Override
      	public Criteria getCriteria(FormItemFunctionContext itemContext) {
      		if (itemContext.getFormItem().getValue() == null)
      			return null;
      		return new AdvancedCriteria(OperatorId.OR, new Criterion[] {
      				new Criterion("SHORTNAME", OperatorId.ISTARTS_WITH, [B]((ComboBoxItem) itemContext.getFormItem()).getEnteredValue()[/B]),
      				new Criterion("NAME", OperatorId.ICONTAINS, [B]((ComboBoxItem) itemContext.getFormItem()).getEnteredValue()[/B]) });
      	}
      });
      This works 99% perfect - the difference to the default behaviour is that in absence of setPickListFilterCriteriaFunction() the ComboBoxItem does not filter if you press the arrow button directly after load. Is this possible as well? I did not find a "hasChanges()" I could use to tell these cases apart. How does the default implementation do this?

      Best regards
      Blama

      Comment


        #4
        See comboBoxItem.filterWithValue.

        Comment


          #5
          Hi Isomorphic,

          I changed the code to
          Code:
          setPickListFilterCriteriaFunction(new FormItemCriteriaFunction() {
          	@Override
          	public Criteria getCriteria(FormItemFunctionContext itemContext) {
          		if (itemContext.getFormItem().getValue() == null)
          			return null;
          		if (!((ComboBoxItem) itemContext.getFormItem()).getFilterWithValue())
          			return null;
          		else
          			return new AdvancedCriteria(OperatorId.OR, new Criterion[] {
          					new Criterion("SHORTNAME", OperatorId.ISTARTS_WITH, ((ComboBoxItem) itemContext.getFormItem()).getEnteredValue()),
          					new Criterion("NAME", OperatorId.ICONTAINS, ((ComboBoxItem) itemContext.getFormItem()).getEnteredValue()) });
          	}
          });
          and it is now behaving as wanted.

          Thank you very much
          Blama

          Comment

          Working...
          X