Announcement

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

    Problem with FilterBuilder DatePicker

    SmartClient Version: v9.1p_2014-09-09/PowerEdition Deployment (built 2014-09-09)
    Browser: Firefox 10.0.4

    If you create a filter builder and set the default time to one hour in the past (using an AdvancedCriteria), the DatePicker does not pop up when you click on it. It only starts working after you've modified the date manually, or via the dropdown.

    Note, I've also modified the default date format via DateUtil.

    I've created a standalone test case by modifying the CustomDS example:

    CustomDS.java:
    Code:
    package com.smartgwt.sample.client;
    
    import java.util.Date;
    
    import com.smartgwt.client.util.DateUtil;
    import com.google.gwt.core.client.EntryPoint;
    import com.google.gwt.core.client.GWT;
    import com.google.gwt.i18n.client.DateTimeFormat;
    import com.smartgwt.client.core.KeyIdentifier;
    import com.smartgwt.client.data.AdvancedCriteria;
    import com.smartgwt.client.data.Criterion;
    import com.smartgwt.client.data.DataSource;
    import com.smartgwt.client.data.Record;
    import com.smartgwt.client.data.fields.*;
    import com.smartgwt.client.types.OperatorId;
    import com.smartgwt.client.util.DateDisplayFormatter;
    import com.smartgwt.client.util.DateParser;
    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.Label;
    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.FilterBuilder;
    import com.smartgwt.client.widgets.grid.ListGrid;
    import com.smartgwt.client.widgets.grid.ListGridRecord;
    import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
    import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
    import com.smartgwt.client.widgets.layout.VStack;
    import com.smartgwt.client.widgets.toolbar.ToolStrip;
    import com.smartgwt.client.widgets.viewer.DetailViewer;
    
    /**
     * Entry point classes define <code>onModuleLoad()</code>.
     */
    public class CustomDS implements EntryPoint {
    	private ListGrid boundList;
    	private DynamicForm boundForm;
    	private IButton saveBtn;
    	private DetailViewer boundViewer;
    	private IButton newBtn;
    
    	final static String DATE_FORMAT = "MM/dd/yyyy HH:mm:ss.SSS";
    	public static final DateTimeFormat formatter = DateTimeFormat
    			.getFormat(DATE_FORMAT);
    
    	/**
    	 * This is the entry point method.
    	 */
    	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();
    			}
    		});
    
    		// instantiate DataSource on the client only (this example explicitly
    		// bypasses
    		// ISC server-side DataSource management)
    
    		DataSource dataSource = new DataSource();
    		dataSource.setDataURL(GWT.getModuleBaseURL()
    				+ "/supplyItemOperations.rpc");
    		dataSource.setID("supplyItem");
    
    		DataSourceSequenceField itemID = new DataSourceSequenceField("itemID");
    		itemID.setPrimaryKey(true);
    		itemID.setHidden(true);
    
    		DataSourceTextField itemName = new DataSourceTextField("itemName",
    				"Item", 128, true);
    
    		DataSourceTextField SKU = new DataSourceTextField("SKU", "SKU", 10);
    		// SKU.setCanFilter(false);
    
    		DataSourceTextField description = new DataSourceTextField(
    				"description", "Description");
    		DataSourceTextField category = new DataSourceTextField("category",
    				"Category", 128);
    		DataSourceTextField units = new DataSourceTextField("units", "Units", 5);
    
    		DataSourceFloatField unitCost = new DataSourceFloatField("unitCost",
    				"Unit Cost");
    		DataSourceBooleanField inStock = new DataSourceBooleanField("inStock",
    				"In Stock");
    
    		DataSourceDateField nextShipment = new DataSourceDateField(
    				"nextShipment", "Next Shipment");
    
    		dataSource.setFields(itemID, itemName, SKU, description, category,
    				units, unitCost, inStock, nextShipment);
    
    		VStack vStack = new VStack();
    		vStack.setLeft(175);
    		vStack.setTop(75);
    		vStack.setWidth("70%");
    		vStack.setMembersMargin(20);
    
    		Label label = new Label();
    		label.setContents("<ul>"
    				+ "<li>click a record in the grid to view and edit that record in the form</li>"
    				+ "<li>click <b>New</b> to start editing a new record in the form</li>"
    				+ "<li>click <b>Save</b> to save changes to a new or edited record in the form</li>"
    				+ "<li>click <b>Clear</b> to clear all fields in the form</li>"
    				+ "<li>click <b>Filter</b> to filter (substring match) the grid based on form values</li>"
    				+ "<li>click <b>Fetch</b> to fetch records (exact match) for the grid based on form values</li>"
    				+ "<li>double-click a record in the grid to edit inline (press Return, or arrow/tab to another record, to save)</li>"
    				+ "</ul>");
    		vStack.addMember(label);
    
    		final FilterBuilder filterBuilder = new FilterBuilder() {
    		};
    		filterBuilder.setMatchAllTitle("all");
    		filterBuilder.setMatchAnyTitle("any");
    		filterBuilder.setMatchNoneTitle("none");
    		filterBuilder.setMargin(5);
    		filterBuilder.setDataSource(dataSource);
    
    		Date filterTime = new Date(System.currentTimeMillis()
    				- (1 * 3600 * 1000));
    		Criterion[] criteriaList = new Criterion[] { new Criterion(
    				"nextShipment", OperatorId.GREATER_THAN, filterTime) };
    		AdvancedCriteria defaultCriteria = new AdvancedCriteria(OperatorId.AND,
    				criteriaList);
    		filterBuilder.setCriteria(defaultCriteria);
    
    		vStack.addMember(filterBuilder);
    
    		boundList = new ListGrid();
    		boundList.setHeight(200);
    		boundList.setCanEdit(true);
    		boundList.setDataSource(dataSource);
    
    		boundList.addRecordClickHandler(new RecordClickHandler() {
    			public void onRecordClick(RecordClickEvent event) {
    				Record record = event.getRecord();
    				boundForm.editRecord(record);
    				saveBtn.enable();
    				boundViewer.viewSelectedData(boundList);
    			}
    		});
    		vStack.addMember(boundList);
    
    		boundForm = new DynamicForm();
    		boundForm.setDataSource(dataSource);
    		boundForm.setNumCols(6);
    		boundForm.setAutoFocus(false);
    		vStack.addMember(boundForm);
    
    		ToolStrip toolbar = new ToolStrip();
    		toolbar.setMembersMargin(10);
    		toolbar.setHeight(22);
    
    		saveBtn = new IButton("Save");
    		saveBtn.addClickHandler(new ClickHandler() {
    			public void onClick(ClickEvent event) {
    				boundForm.saveData();
    				if (!boundForm.hasErrors()) {
    					boundForm.clearValues();
    					saveBtn.disable();
    				}
    			}
    		});
    		toolbar.addMember(saveBtn);
    
    		IButton clearBtn = new IButton("Clear");
    		clearBtn.addClickHandler(new ClickHandler() {
    			public void onClick(ClickEvent event) {
    				boundForm.clearValues();
    				saveBtn.disable();
    			}
    		});
    		toolbar.addMember(clearBtn);
    
    		IButton filterBtn = new IButton("Filter");
    		filterBtn.addClickHandler(new ClickHandler() {
    			public void onClick(ClickEvent event) {
    				boundList.filterData(boundForm.getValuesAsCriteria());
    				saveBtn.disable();
    			}
    		});
    		toolbar.addMember(filterBtn);
    
    		IButton fetchBtn = new IButton("Fetch");
    		fetchBtn.addClickHandler(new ClickHandler() {
    			public void onClick(ClickEvent event) {
    				boundList.fetchData(boundForm.getValuesAsCriteria());
    				saveBtn.disable();
    			}
    		});
    		toolbar.addMember(fetchBtn);
    
    		IButton deleteBtn = new IButton("Delete");
    		deleteBtn.addClickHandler(new ClickHandler() {
    			public void onClick(ClickEvent event) {
    				boundList.removeSelectedData();
    				boundList.deselectAllRecords();
    			}
    		});
    		toolbar.addMember(deleteBtn);
    
    		vStack.addMember(toolbar);
    
    		boundViewer = new DetailViewer();
    		boundViewer.setDataSource(dataSource);
    		vStack.addMember(boundViewer);
    
    		DateDisplayFormatter dateFormatter = new DateDisplayFormatter() {
    			@Override
    			public String format(Date date) {
    				return formatter.format(date);
    			}
    		};
    		DateUtil.setShortDatetimeDisplayFormatter(dateFormatter);
    		DateUtil.setNormalDateDisplayFormatter(dateFormatter);
    		DateUtil.setDateInputFormat(DATE_FORMAT);
    
    		DateParser parser = new DateParser() {
    			@Override
    			public Date parse(String dateString) {
    				Date date = new Date();
    
    				if (dateString != null) {
    					date = formatter.parse(dateString);
    				}
    				return date;
    			}
    		};
    		DateUtil.setDateParser(parser);
    				
    		vStack.draw();
    
    		boundList.filterData(null);
    	}
    
    }

    #2
    The actual error is coming from a string formatted as "MM/DD/YYYY" being passed to the DateTimeFormat.parse method, when it's specified format is actually "MM/dd/yyyy HH:mm"
    This is specifically happening when the default formatted value is passed to the parser you specified via DateUtil.setDateParser(parser);

    From a quick look, you've got a couple of usage issues here:
    - The DateUtil.setDateInputFormat(...) method doesn't take a full format string like the one in your sample - just a 3 character value like "MDY"
    - You're calling setShortDatetimeDisplayFormatter(...) and setNormalDateDisplayFormatter(...). These apply to different data types ("date" vs "datetime"). The DataSource field in question is of type "date" btw.

    Having said that, we're investigating this report as it seems like even with these corrected, we may be failing to call the custom parser in all cases.
    We'll follow up with more information when we have it.

    Regards
    Isomorphic Software

    Comment


      #3
      We've had a quick look into this - we're unclear as to whether you left all the original builtinds code in your test-case on purpose, but below is a minimal version of your test-case that works as expected.

      There are some inline comments that explain the changes.

      Let us know if this doesn't fully cover your circumstances.

      Code:
      public class BuiltInDS implements EntryPoint {
      
      	// NOTE: millisecond precision is *not* enabled for DataSources by default - if you need it, please read the doc 
      	// for DataSource.setTrimMilliseconds(), in particular the bit that starts "The SQLDataSource was 
      	// designed for accuracy to the nearest second, and making it support millisecond accuracy requires 
      	// a couple of steps"
      	final static String DATE_FORMAT = "MM/dd/yyyy HH:mm:ss.SSS";
          public static final DateTimeFormat formatter = DateTimeFormat
                          .getFormat(DATE_FORMAT);
      
          /**
           * This is the entry point method.
           */
          public void onModuleLoad() {
      
          	// *** calls to set DateUtil globals must be made before any widgets are created 
              DateDisplayFormatter dateFormatter = new DateDisplayFormatter() {
                  @Override
                  public String format(Date date) {
                          return formatter.format(date);
                  }
      	    };
      	    DateUtil.setShortDatetimeDisplayFormatter(dateFormatter);
      	    DateUtil.setNormalDateDisplayFormatter(dateFormatter);
      	    // inputFormat is a 3-char string
      	    DateUtil.setDateInputFormat("MDY");
      
      	    DateParser parser = new DateParser() {
      	            @Override
      	            public Date parse(String dateString) {
      	                    Date date = new Date();
      	
      	                    if (dateString != null) {
      	                            date = formatter.parse(dateString);
      	                    }
      	                    return date;
      	            }
      	    };
      	    DateUtil.setDateParser(parser);
      
      	    // DS
              DataSource dataSource = new DataSource();
              dataSource.setID("testDS");
              dataSource.setClientOnly(true);
      
              // fields
              DataSourceSequenceField pkField = new DataSourceSequenceField("pkField");
              pkField.setPrimaryKey(true);
              pkField.setHidden(true);
              // if you want to maintain time-elements, you need a "datetime" field, because "date" type 
              // fields are enforced as logicalDates, which discard all time-elements
              DataSourceDateTimeField dateTimeField = new DataSourceDateTimeField("dateTimeField", "DateTime");
      
              dataSource.setFields(pkField, dateTimeField);
      
              final FilterBuilder filterBuilder = new FilterBuilder();
              filterBuilder.setDataSource(dataSource);
      
              Date filterTime = new Date(System.currentTimeMillis() - (1 * 3600 * 1000));
              Criterion[] criteriaList = new Criterion[] { new Criterion("dateTimeField", OperatorId.GREATER_THAN, filterTime) };
              AdvancedCriteria defaultCriteria = new AdvancedCriteria(OperatorId.AND, criteriaList);
              filterBuilder.setCriteria(defaultCriteria);
      
              filterBuilder.show();
          }
      }

      Comment


        #4
        That fixed it, thanks!

        Comment

        Working...
        X