Announcement

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

    Advice needed: Use SelectItem (with AdvancedCriteria as Value) in ListGrid Filterrow

    Hi Isomorphic,

    I have the following use case:
    I want a ListGrid with a Amount-field that can groupBy this field. The grouping shouldn't be by the exact value, but in value-ranges, e.g. borders[10,20,50] becomes 4 groups ("<10", "10-20", "20-50", ">50").
    I solved this for the display, but I'm stuck at the filterRow of the ListGrid, as the value for the selected item isn't interpreted as the AdvancedCriteria it is, but as object or pretty long string. Please see the valueMaps used in SelectItemAmount.

    I have this code:

    ListGridFieldAmount (works):
    Code:
    package com.lmscompany.lms.client.ui.listgridfield;
    
    import java.util.Arrays;
    
    import com.google.gwt.i18n.client.NumberFormat;
    import com.lmscompany.lms.client.ui.formitem.SelectItemAmount;
    import com.smartgwt.client.widgets.grid.CellFormatter;
    import com.smartgwt.client.widgets.grid.GroupNode;
    import com.smartgwt.client.widgets.grid.GroupTitleRenderer;
    import com.smartgwt.client.widgets.grid.GroupValueFunction;
    import com.smartgwt.client.widgets.grid.ListGrid;
    import com.smartgwt.client.widgets.grid.ListGridField;
    import com.smartgwt.client.widgets.grid.ListGridRecord;
    
    public final class ListGridFieldAmount extends ListGridField {
    	public ListGridFieldAmount(String name, final String subject, [B]final Integer[] borders[/B]) {
    		super(name);
    
    		setCanFilter(true);
    		[B]setFilterEditorProperties(new SelectItemAmount(name, borders));
    [/B]
    		setCellFormatter(new CellFormatter() {
    			public String format(Object value, ListGridRecord record, int rowNum, int colNum) {
    				if (value == null)
    					return null;
    				else
    					return formatNumberValue(value);
    			}
    		});
    
    		setCanGroupBy(true);
    		setGroupValueFunction(new GroupValueFunction() {
    			@Override
    			public Object getGroupValue(Object value, ListGridRecord record, ListGridField field, String fieldName,
    					ListGrid grid) {
    				Integer currentValue = record.getAttributeAsInt(ListGridFieldAmount.this.getName());
    				if (currentValue == null)
    					return subject + " unbekannt";
    				else {
    					Arrays.sort(borders);
    					for (int i = 0; i < borders.length; i++) {
    						if (currentValue <= borders[i]) {
    							if (i == 0)
    								return "< " + formatNumberValue(borders[i]);
    							else
    								return formatNumberValue(borders[i - 1]) + " - " + formatNumberValue(borders[i]);
    						}
    					}
    					return "> " + formatNumberValue(borders[borders.length - 1]);
    				}
    			}
    		});
    
    		setGroupTitleRenderer(new GroupTitleRenderer() {
    			public String getGroupTitle(Object groupValue, GroupNode groupNode, ListGridField field, String fieldName,
    					ListGrid grid) {
    				return ((String) groupValue) + " (" + groupNode.getGroupMembers().length + ")";
    			}
    		});
    	}
    
    	private static String formatNumberValue(Object value) {
    		String val = null;
    		try {
    			NumberFormat nf = NumberFormat.getFormat("###,###,###,###");
    			val = nf.format(((Number) value).longValue());
    		} catch (Exception e) {
    			return value.toString();
    		}
    		return val + " ";
    	}
    }
    SelectItemAmount (does not work, see the setValueMap())
    Code:
    package com.lmscompany.lms.client.ui.formitem;
    
    import java.util.Arrays;
    import java.util.LinkedHashMap;
    
    import com.google.gwt.i18n.client.NumberFormat;
    import com.smartgwt.client.data.AdvancedCriteria;
    import com.smartgwt.client.data.Criterion;
    import com.smartgwt.client.types.OperatorId;
    import com.smartgwt.client.widgets.form.fields.SelectItem;
    
    public class SelectItemAmount extends SelectItem {
    
    	public SelectItemAmount(final String name, [B]final Integer[] borders[/B]) {
    		super(name);
    
    		LinkedHashMap<AdvancedCriteria, String> m1 = new LinkedHashMap<AdvancedCriteria, String>();
    		LinkedHashMap<String, String> m2 = new LinkedHashMap<String, String>();
    		LinkedHashMap<String, String> m3 = new LinkedHashMap<String, String>();
    		String title = null;
    		Arrays.sort(borders);
    
    		for (int i = 0; i <= borders.length; i++) {
    			Criterion c1 = null;
    			Criterion c2 = null;
    			AdvancedCriteria ac = new AdvancedCriteria(OperatorId.AND);
    			if (i == 0) {
    				title = "< " + formatNumberValue(borders[i]);
    				c2 = new Criterion(name, OperatorId.LESS_THAN, borders[i]);
    				ac.addCriteria(c2);
    			}
    			if (i > 0 && i < borders.length) {
    				title = formatNumberValue(borders[i - 1]) + " - " + formatNumberValue(borders[i]);
    				c1 = new Criterion(name, OperatorId.GREATER_OR_EQUAL, borders[i - 1]);
    				c2 = new Criterion(name, OperatorId.LESS_THAN, borders[i]);
    				ac.addCriteria(c1);
    				ac.addCriteria(c2);
    			}
    			if (i == borders.length) {
    				title = ">= " + formatNumberValue(borders[i - 1]);
    				c1 = new Criterion(name, OperatorId.GREATER_OR_EQUAL, borders[i - 1]);
    				ac.addCriteria(c1);
    			}
    			m1.put(ac, title);
    			m2.put(ac.toString(), title);
    			m3.put(ac.toJSON(), title);
    		}
    		[B]// setValueMap(m1); //doesn't work[/B]
    		[B]// setValueMap(m2); //doesn't work[/B]
    		[B]setValueMap(m3); // doesn't work[/B]
    	}
    
    	private static String formatNumberValue(Object value) {
    		String val = null;
    		try {
    			NumberFormat nf = NumberFormat.getFormat("###,###,###,###");
    			val = nf.format(((Number) value).longValue());
    		} catch (Exception e) {
    			return value.toString();
    		}
    		return val + " ";
    	}
    }
    Server-side error code is e.g.
    Code:
    === 2013-10-23 18:46:32,742 [c-16] DEBUG RPCManager - Request #1 (DSRequest) payload: {
        criteria:{
            _constructor:"AdvancedCriteria",
            operator:"and",
            criteria:[
                {
                    operator:"notNull",
                    fieldName:"TEST_ID"
                },
                {
                    fieldName:"GUESSED_VOLUME",
                    operator:"equals",
                    [B]value:"{\r    \"operator\":\"and\", \r    \"_constructor\":\"AdvancedCriteria\", \r    \"criteria\":[\r        {\r            \"fieldName\":\"GUESSED_VOLUME\", \r            \"operator\":\"greaterOrEqual\", \r            \"value\":100\r        }, \r        {\r            \"fieldName\":\"GUESSED_VOLUME\", \r            \"operator\":\"lessThan\", \r            \"value\":200\r        }\r    ]\r}"[/B]
                }
            ]
        },
        operationConfig:{
            dataSource:"V_TESTVIEW",
            operationType:"fetch",
            textMatchStyle:"substring"
        },
        startRow:0,
        endRow:75,
        sortBy:[
            "TEST_NAME"
        ],
        componentId:"isc_LeadVLayout_3$2$1_2",
        appID:"builtinApplication",
        operation:"V_TESTVIEW_fetch",
        oldValues:{
            _constructor:"AdvancedCriteria",
            operator:"and",
            criteria:[
                {
                    operator:"notNull",
                    fieldName:"TEST_ID"
                },
                {
                    fieldName:"GUESSED_VOLUME",
                    operator:"equals",
                    value:[B]"{\r    \"operator\":\"and\", \r    \"_constructor\":\"AdvancedCriteria\", \r    \"criteria\":[\r        {\r            \"fieldName\":\"GUESSED_VOLUME\", \r            \"operator\":\"greaterOrEqual\", \r            \"value\":100\r        }, \r        {\r            \"fieldName\":\"GUESSED_VOLUME\", \r            \"operator\":\"lessThan\", \r            \"value\":200\r        }\r    ]\r}"[/B]
                }
            ]
        }
    }
    Do you have an advice on how I get the framework to interpret the SelectItem's value as AdvancedCriteria instead of as string. I'm using the current nightly.

    Thank you & Best regards,
    Blama

    #2
    Hi Isomorphic,

    I tried around and use now
    Code:
    public final class TextItemAmount extends TextItem {
    
    	public TextItemAmount(String name) {
    		super(name);
    		setAllowExpressions(true);
    	}
    }
    , which gives me the needed filter possibilities, as it produces the needed criteria, but not as SelectItem.

    @Everone: I just found FormItem.setCriterionGetter(FormItemCriterionGetter) which looks very promising. I'll try and update this post.

    Best regards,
    Blama
    Last edited by Blama; 24 Oct 2013, 00:38.

    Comment


      #3
      Hello everyone,

      I got it working, but have a small follow-up problem.
      Below is the working code that does the correct filtering.
      What doesn't work: After filtering, the SelectItem shows the empty entry at the top of the list and all following Filter attempts using the SelectItem fail by showing no data. Also, the RPC tab in the Developer Console shows no activity for the subsequent filter attempts.
      This might be related to my setCriterionSetter(FormItemCriterionSetter), but this code is never called (breakpoints are not hit). Using setCriteriaField(criteriaField) makes to difference, which is correct as this ListGridField is the only one for this DataSourceField.

      @Isomorphic: Do you have any hints?

      Best regards,
      Blama


      Code:
      package com.lmscompany.lms.client.ui.formitem;
      
      import java.util.Arrays;
      import java.util.LinkedHashMap;
      
      import com.google.gwt.i18n.client.NumberFormat;
      import com.smartgwt.client.data.AdvancedCriteria;
      import com.smartgwt.client.data.Criterion;
      import com.smartgwt.client.types.OperatorId;
      import com.smartgwt.client.types.TextMatchStyle;
      import com.smartgwt.client.widgets.form.DynamicForm;
      import com.smartgwt.client.widgets.form.FormItemCriterionGetter;
      import com.smartgwt.client.widgets.form.FormItemCriterionSetter;
      import com.smartgwt.client.widgets.form.fields.FormItem;
      import com.smartgwt.client.widgets.form.fields.SelectItem;
      
      public class SelectItemAmount extends SelectItem {
      
      	// See JavaDoc for setOperator(OperatorId) and
      	// setCriterionGetter(FormItemCriterionGetter) to see why this method is
      	// overridden here. Without, SC.say(hasAdvancedCriteria().toString()) gives a
      	// JavaScript error
      	// ("(TypeError) @com.smartgwt.client.widgets.form.fields.FormItem::hasAdvancedCriteria()([]): self.hasAdvancedCriteria is not a function").
      	@Override
      	public Boolean hasAdvancedCriteria() {
      		return true;
      	};
      
      	public SelectItemAmount(final String name, final Integer[] borders) {
      		super(name);
      		setCriteriaField(name);
      
      		setOperator(OperatorId.AND);
      		LinkedHashMap<String, String> m = new LinkedHashMap<String, String>();
      		String title = null;
      		Arrays.sort(borders);
      
      		for (int i = 0; i <= borders.length; i++) {
      			Criterion c1 = null;
      			Criterion c2 = null;
      			AdvancedCriteria ac = new AdvancedCriteria(OperatorId.AND);
      			if (i == 0) {
      				title = "< " + formatNumberValue(borders[i]);
      				c2 = new Criterion(name, OperatorId.LESS_THAN, borders[i]);
      				ac.addCriteria(c2);
      			}
      			if (i > 0 && i < borders.length) {
      				title = formatNumberValue(borders[i - 1]) + " - " + formatNumberValue(borders[i]);
      				c1 = new Criterion(name, OperatorId.GREATER_OR_EQUAL, borders[i - 1]);
      				c2 = new Criterion(name, OperatorId.LESS_THAN, borders[i]);
      				ac.addCriteria(c1);
      				ac.addCriteria(c2);
      			}
      			if (i == borders.length) {
      				title = ">= " + formatNumberValue(borders[i - 1]);
      				c1 = new Criterion(name, OperatorId.GREATER_OR_EQUAL, borders[i - 1]);
      				ac.addCriteria(c1);
      			}
      			m.put(ac.toJSON(), title);
      		}
      		setValueMap(m);
      
      		setCriterionGetter(new FormItemCriterionGetter() {
      			@Override
      			public Criterion getCriterion(DynamicForm form, FormItem item, TextMatchStyle textMatchStyle) {
      				if (item == null || item.getValue() == null)
      					return null;
      				else
      					return AdvancedCriteria.fromJSON(item.getValue().toString());
      			}
      
      			@Override
      			public Criterion getCriterion(DynamicForm form, FormItem item) {
      				if (item == null || item.getValue() == null)
      					return null;
      				else
      					return AdvancedCriteria.fromJSON(item.getValue().toString());
      			}
      		});
      
      		//Not used/hit
      		setCriterionSetter(new FormItemCriterionSetter() {
      			@Override
      			public void setCriterion(DynamicForm form, FormItem item, Criterion criterion) {
      				item.setValue(criterion.asAdvancedCriteria().toJSON());
      			}
      		});
      	}
      
      	private static String formatNumberValue(Object value) {
      		String val = null;
      		try {
      			NumberFormat nf = NumberFormat.getFormat("###,###,###,###");
      			val = nf.format(((Number) value).longValue());
      		} catch (Exception e) {
      			return value.toString();
      		}
      		return val + " ";
      	}
      }

      Comment


        #4
        Hi,

        I just saw that I get the following warning in the console. This might be relevant:

        Code:
        [ERROR] [lms] - 12:14:00.699:IFCS7:WARN:RecordEditor:isc_LeadVLayout_3$2$1_5filterEditor:No editable fields in this record editor. Check the 'canFilter' property for each field in isc_LeadVLayout_3$2$1_5
        I'm using the nightly v9.0p_2013-10-23 with Eclipse DevMode and FF24. If necessary I'll post the whole ds.xml and ListGrid code.

        Best regards,
        Blama

        Comment

        Working...
        X