Announcement

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

    FilterBuilder FieldPicker using PickTreeItem

    I need for a FilterBuilder to display its list of fields hierarchically. So that given a datasource like

    Code:
        <fields>  
            <field name="ORDERID" type="sequence" primaryKey="true">
                <title>Order ID</title>
            </field>
            <field name="CUSTOMERNAME">
                <title>Customer Name</title>
            </field>
            <field name="ORDERDATE">
                <title>Order Date</title>
            </field>
            <field name="TRACKINGNUMBER">
                <title>Tracking Number</title>
            </field>
        </fields>
    the list of fields can be presented for example

    Code:
    Customer
      Customer Name
    Order
      Order ID
      Order Date
    I thought a reasonable approach might be one like

    Code:
    import com.google.gwt.core.client.EntryPoint;
    import com.google.gwt.core.client.GWT;
    import com.smartgwt.client.core.KeyIdentifier;
    import com.smartgwt.client.data.DataSource;
    import com.smartgwt.client.types.TreeModelType;
    import com.smartgwt.client.util.KeyCallback;
    import com.smartgwt.client.util.Page;
    import com.smartgwt.client.util.SC;
    import com.smartgwt.client.widgets.form.FilterBuilder;
    import com.smartgwt.client.widgets.form.fields.PickTreeItem;
    import com.smartgwt.client.widgets.layout.VLayout;
    import com.smartgwt.client.widgets.tree.Tree;
    import com.smartgwt.client.widgets.tree.TreeNode;
    
    public final class TreeFilterEntryPoint implements EntryPoint {
    
    	private static final String ATTR_NAME = "name";
    	private static final String ATTR_TITLE = "title";
    	
    	public void onModuleLoad() {
    
    		VLayout layout = new VLayout();
    		layout.setWidth100();
    		layout.setHeight100();
    		
    		PickTreeItem pt = new PickTreeItem();
    		pt.setValueTree(buildTree());
    		
    		final FilterBuilder filterBuilder = new FilterBuilder();  
    		filterBuilder.setDataSource(DataSource.get("Order"));
                    filterBuilder.setFieldPickerProperties(pt);
    
                    layout.addMember(filterBuilder);		
    		
    		layout.draw();
    
    		if (!GWT.isScript()) {
    			KeyIdentifier debugKey = new KeyIdentifier();
    			debugKey.setCtrlKey(true);
    			debugKey.setAltKey(true);
    			debugKey.setKeyName("D");
    			Page.registerKey(debugKey, new KeyCallback() {
    				public void execute(String keyName) {
    					SC.showConsole();
    				}
    			});
    		}
    	}
    	
    	private Tree buildTree() {
    		Tree tree = new Tree();
    		tree.setModelType(TreeModelType.CHILDREN);
    		tree.setIdField(ATTR_NAME);
    		tree.setNameProperty(ATTR_TITLE);
    		
    		TreeNode orderNodes = new TreeNode("Order");
    		FieldNode orderIdNode = new FieldNode("ORDERID", "Order ID");
    		FieldNode orderDateNode = new FieldNode("ORDERDATE", "Order Date");
    		
    		TreeNode customerNodes = new TreeNode("Customer");
    		FieldNode customerName = new FieldNode("CUSTOMERNAME", "Customer Name");
    		
    		customerNodes.setChildren(new TreeNode[] {customerName});
    		orderNodes.setChildren(new TreeNode[] {orderIdNode, orderDateNode});
    		
    		tree.setData(new TreeNode[]{orderNodes});
    		return tree;
    	}
    	
    	private class FieldNode extends TreeNode {
    		public FieldNode(String name, String title) {
    			setAttribute(ATTR_NAME, name);
    			setAttribute(ATTR_TITLE, title);
    		}
    	}
    }
    When the layout is drawn, my FilterBuilder looks just the way I meant it to. OrderId is selected, operator is set to 'contains', and the right operand is empty. Good.

    1) When I switch Order ID's operator to one of the 'field comparators' (e.g., 'matches other field') the right operand presents me with the same old SelectItem. Should it not respect the FieldPickerProperties?

    2) When I switch the left operand to anything other than Order ID and then change the operator, I am greeted with the following:

    Code:
    [ERROR] [TreeFilter] - 17:24:36.869:IFCS7:WARN:Log:TypeError: _3 is undefined
        Canvas.addFieldValidators(_1=>[object Array]) @ TreeFilter/sc/modules/ISC_Core.js:3576
        DynamicForm.addItems(_1=>[object Array]) @ TreeFilter/sc/modules/ISC_Forms.js:289
        FilterClause.updateValueItems(_1=>undef,  _2=>{Obj},  _3=>"/Order/Order Date") @ TreeFilter/sc/modules/ISC_DataBinding.js:3343
        FilterClause.operatorChanged(=>{Obj}) @ TreeFilter/sc/modules/ISC_DataBinding.js:3341
        unnamed({Obj}, {Obj}, "equals") @ TreeFilter/sc/modules/ISC_DataBinding.js:3269
        FormItem.handleChanged(_1=>"equals") @ TreeFilter/sc/modules/ISC_Forms.js:1389
        FormItem.storeValue(_1=>"equals") @ TreeFilter/sc/modules/ISC_Forms.js:1387
        FormItem._updateValue("equals") @ TreeFilter/sc/modules/ISC_Forms.js:1384
        SelectItem.updateValue() @ TreeFilter/sc/modules/ISC_Forms.js:2355
        SelectItem.changeToValue(_1=>"equals",  _2=>true) @ TreeFilter/sc/modules/ISC_Forms.js:2346
        SelectItem.pickValue(_1=>"equals") @ TreeFilter/sc/modules/ISC_Forms.js:2390
        PickListMenu.itemClick(_1=>{Obj}) @ TreeFilter/sc/modules/ISC_Forms.js:2147
        PickListMenu.recordClick(viewer=>{Obj}, record=>{Obj}, recordNum=>6, field=>{Obj}, fieldNum=>0, value=>"equals", rawValue=>"equals") @ TreeFilter/sc/modules/ISC_Forms.js:2142
        ListGrid.rowClick(record=>{Obj}, rowNum=>6, colNum=>0) @ TreeFilter/sc/modules/ISC_Grids.js:1784
        anonymous({Obj}, 6, 0) @ TreeFilter/sc/modules/ISC_Grids.js:1046
        GridRenderer._rowClick(6, 0) @ TreeFilter/sc/modules/ISC_Grids.js:843
        Class.invokeSuper(_1=>null,  _2=>"$29y") @ TreeFilter/sc/modules/ISC_Core.js:307
        Class.Super(_1=>"$29y",  _2=>[object Arguments]) @ TreeFilter/sc/modules/ISC_Core.js:299
        GridBody._rowClick(6, 0) @ TreeFilter/sc/modules/ISC_Grids.js:921
        GridRenderer.click({Obj}, undef) @ TreeFilter/sc/modules/ISC_Grids.js:840
        Canvas.handleClick({Obj}, undef) @ TreeFilter/sc/modules/ISC_Core.js:3245
        [c]EventHandler.bubbleEvent(_1=>{Obj},  _2=>"click") @ TreeFilter/sc/modules/ISC_Core.js:1668
        [c]EventHandler.handleClick(_1=>{Obj}) @ TreeFilter/sc/modules/ISC_Core.js:1505
        EventHandler._handleMouseUp([object MouseEvent], undef) @ TreeFilter/sc/modules/ISC_Core.js:1492
        [c]EventHandler.handleMouseUp(_1=>[object MouseEvent]) @ TreeFilter/sc/modules/ISC_Core.js:1483
        [c]EventHandler.dispatch(_1=>isc_c_EventHandler_handleMouseUp,  _2=>[object MouseEvent]) @ TreeFilter/sc/modules/ISC_Core.js:1731
        anonymous([object MouseEvent]) @ TreeFilter/sc/modules/ISC_Core.js:61
        unnamed() @
    This with power ed. 3.0.p20120303. Where is my mistake, please?

    #2
    Switching the FieldPicker to a different type of FormItem with a different data model isn't a use case we had in mind, so the FilterBuilder is being tripped up by the absence of expected APIs.

    A better way of doing this, which will also support load on demand for larger trees and is generally a quicker UI for picking an item, is to stick with a SelectItem and create the appearance of a tree with indentation. For example, you can return a third property "treeLevel" and add a CellFormatter via PickListFields that indents the value according to it's treeLevel.

    Comment


      #3
      Fair enough, but the API doc does say that fieldPickerProperties takes any FormItem. Can you clarify whether or not any other FormItem is supported?

      I'm just not sure I'll be able to get away with an indented SelectItem. If I am, can you confirm that I should see my issue #1 behave as expected? i.e., the 2nd SelectItem would take the appearance of the first?

      Comment


        #4
        The API lets you use more than one FormItem type (eg ComboBoxItem or SelectItem), it just didn't expect one using a Tree as it's data model.

        We'll check on the matchesField case.

        Comment


          #5
          Originally posted by Isomorphic
          We'll check on the matchesField case.
          A quick test on my end seems to show that fieldPickerProperties is not respected in the matchesField case. Should it be?

          Comment


            #6
            It's a little ambiguous because while it is a field picker, it's also a valueField. Current thinking is that we will apply both sets of customizations to the field, with the fieldPickerProperties winning. Should be roughly late this week.

            Comment


              #7
              I'm still struggling with this a bit. I thought I might use FilterBuilder.setFieldDataSource to get my tree data in the list. This works, but then it seems that my cellFormatter callback is never fired?

              A slight modification to a showcase example:

              Code:
              	public void onModuleLoad() {
              
              		ListGridRecord testData[] = new ListGridRecord[200];  
              		  
                      for(int i=0;i<200;i++)  
                      {  
                          ListGridRecord record = new ListGridRecord();  
                          record.setAttribute("name", "field" + i);  
                          record.setAttribute("title", "Field " + i);  
                          record.setAttribute("type", "text");  
                          testData[i] = record;  
                      }  
                
                      DataSource bigFilterDS = new DataSource();  
                      bigFilterDS.setClientOnly(true);  
                
                      DataSourceTextField nameField = new DataSourceTextField("name");  
                      DataSourceTextField titleField = new DataSourceTextField("title");  
                      DataSourceTextField typeField = new DataSourceTextField("type");  
                
                      bigFilterDS.setFields(nameField, titleField, typeField);  
                      bigFilterDS.setTestData(testData);  
                
                      FilterBuilder filterBuilder = new FilterBuilder();  
                      filterBuilder.setFieldDataSource(bigFilterDS);  
                
                      AdvancedCriteria criteria = new AdvancedCriteria(OperatorId.AND, new AdvancedCriteria[] {  
                              new AdvancedCriteria("field2", OperatorId.ISTARTS_WITH, "C"),  
                              new AdvancedCriteria(OperatorId.OR, new AdvancedCriteria[] {  
                                  new AdvancedCriteria("field73", OperatorId.NOT_EQUAL_FIELD, "field191"),  
                                  new AdvancedCriteria("field130", OperatorId.ICONTAINS, "B")  
                              })  
                      });  
                
                      filterBuilder.setCriteria(criteria);  
                
                      SelectItem formItemProperties = new SelectItem();  
                      formItemProperties.setShowPickerIcon(false);  
                      ListGrid pickListProperties = new ListGrid();
              		pickListProperties.setCellFormatter(new CellFormatter() {
              			public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
              				GWT.log(record.getAttribute("name"));
              				return value.toString();
              			}
              		});
              		formItemProperties.setPickListProperties(pickListProperties);
              		filterBuilder.setFieldPickerProperties(formItemProperties); 
                      
              		filterBuilder.draw();
              
              		if (!GWT.isScript()) {
              			KeyIdentifier debugKey = new KeyIdentifier();
              			debugKey.setCtrlKey(true);
              			debugKey.setAltKey(true);
              			debugKey.setKeyName("D");
              			Page.registerKey(debugKey, new KeyCallback() {
              				public void execute(String keyName) {
              					SC.showConsole();
              				}
              			});
              		}
              	}

              Comment


                #8
                Set it via setPickListFields() as a field-specific CellFormatter. The problem is that the framework is already supplying a field-specific formatter, so that overrides.

                Comment


                  #9
                  We've now added support for the field picker properties being applied to the "other field" chooser in 3.0p and 3.1d branches.

                  The request for PickTreeItem support also came up in a separate thread and we made the changes necessary to support this. The formatted SelectItem is probably still actually a cleaner user experience but if you're interested in experimenting with your original approach it should now work for you. One minor tweak - you'll have to explicitly call pt.setValueField("name"); on the field picker

                  Comment


                    #10
                    That's awesome. Thanks very much for knocking that out.

                    Wll the pick tree support be present in 3.0p as well? And in either case, could I expect that to work with the 'other field' chooser also?

                    Comment


                      #11
                      I had a chance to test today's 3.0p build with the formatted SelectItem. The fieldPickerProperties is displayed properly in the 'other field' chooser, but:

                      1) No fetch is fired when I actually exceute the filter.
                      2) After initially setting the operator to 'other field', attempts to change the criteria (by changing the 1st operand or the operator) add additional 'other field' choosers to the layout. Screenshot attached.

                      Code:
                      08:53:03.600:IFCS9:INFO:layout:isc_PickListMenu_0:adding newMembers: [GridBody ID:isc_PickListMenu_0_body] at position: 0
                      08:53:03.659:IFCS9:INFO:layout:isc_PickListMenu_0:layoutChildren (reason: initial draw):
                      layout specified size: 146w x 1h
                      drawn size: 146w x 98h
                      available size: 146w x 1h (length)
                         [GridBody ID:isc_PickListMenu_0_body]
                            98 drawn length (resizeLength: 1) (policyLength: *) (no length specified)
                            146 drawn breadth (breadth policy: fill)
                      
                      08:53:06.290:IFCS6[E]:INFO:layout:isc_FilterBuilder_0_clause:Restacking, reason: memberResized: (150,0): isc_FilterBuilder_0_clause_clause
                      08:53:06.292:IFCS6[E]:INFO:layout:isc_FilterBuilder_0_clauseStack:Restacking, reason: memberResized: (150,0): isc_FilterBuilder_0_clause
                      08:53:07.485:IFCS4:INFO:layout:isc_PickListMenu_1:adding newMembers: [GridBody ID:isc_PickListMenu_1_body] at position: 0
                      08:53:07.585:IFCS4:INFO:layout:isc_PickListMenu_1:layoutChildren (reason: initial draw):
                      layout specified size: 146w x 1h
                      drawn size: 178w x 302h
                      available size: 146w x 1h (length)
                         [GridBody ID:isc_PickListMenu_1_body]
                            302 drawn length (resizeLength: 1) (policyLength: *) (no length specified)
                            146 drawn breadth (breadth policy: fill)
                      
                      08:53:16.579:IFCS2[E]:INFO:layout:isc_FilterBuilder_0_clause:Restacking, reason: memberResized: (150,0): isc_FilterBuilder_0_clause_clause
                      08:53:16.581:IFCS2[E]:INFO:layout:isc_FilterBuilder_0_clauseStack:Restacking, reason: memberResized: (150,0): isc_FilterBuilder_0_clause
                      Could this be my problem, or have I found a bug?
                      Attached Files

                      Comment


                        #12
                        Still anxious to hear what you make of this... I don't see how it could be a problem on my end - you should be able to use the code posted previously to reproduce it.

                        Comment


                          #13
                          This was on our end.
                          It turned out to be an issue with the SGWT wrapper code that we had missed. Fixed now. Please try the next nightly build and let us know if you hit anything else that doesn't work as expected here

                          Regards
                          Isomorphic Software

                          Comment


                            #14
                            Getting closer, I think. Tested with the 3/27 3.0p nightly (3.1d is missing).

                            Now if I select a field, operator, other field and then switch the operator, the 'other field' value remains in the 2nd operand. Screenshot attached.
                            Attached Files

                            Comment


                              #15
                              Looks like this is not related to the field picker customization - this same behavior (retaining the field name when you move from "matches other field" to "contains" for example) exists without the picker customization

                              However, we agree that it's basically a bug. We'll take care of it
                              --
                              Update - this is now addressed - the change will show up in nightlies going forward
                              Last edited by Isomorphic; 28 Mar 2012, 10:27.

                              Comment

                              Working...
                              X