Announcement

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

    LogicalDate object failing isADate validation

    SmartClient Version: v10.0p_2015-05-09/PowerEdition Deployment (built 2015-05-09)

    We have a CanvasItem in formA which has a canvas consisting of formB. formB includes a DateItem on which there is a changedHandler which stores the new value as the CanvasItem's value. The CanvasItem is used to edit a field defined as type="date" in the datasource. When .validate is called on formA we're getting a validation error on the CanvasItem saying "Must be a date", even when the value is a valid date.

    Using the Chrome debugger we can see that the Object being validated is a LogicalDate, so the comparison being done in the return statement (in the attached screen shot from isc_Core.js) is returning false because it is looking for an object.constructor function named "Date", but the LogicalDate object's constructor function is named "Object".

    The CanvasItem's value is updated by a ChangedHandler on the DateItem like this, where "editor" refers to the CanvasItem.
    Code:
    outerHandoverDate.addChangedHandler(new ChangedHandler() {
      @Override
      public void onChanged(ChangedEvent event) {
        editor.storeValue((Date)event.getValue());
      }
    });
    Why does casting the event value as a Date result in a LogicalDate object? Is that the correct way to store the value? And why does the LogicalDate not validate as a date?
    Attached Files
    Last edited by jay.l.fisher; 18 Jun 2015, 19:01.

    #2
    I would just add this observation that we have seen on this issue: if we compile a single permutation that has no locale support, the date format for entry and display is YYYY-MM-DD and we do NOT get the validation error described by jay.l.fisher above.

    However, if we compile with, say, a permutation for en_US locale and use a client configured for that locale, the date format for display and entry becomes MM/DD/YY and we DO get the validation error.

    So there seems to be something at play here in how the locale settings affect the interpretation of the assigned value.

    Comment


      #3
      Thanks for the notification - we have a developer assigned to look into this and will follow up as soon as we have more information for you.

      Regards
      Isomorphic Software

      Comment


        #4
        We're not sure why the locale support should have any impact on this issue, but we were able to reproduce the underlying problem and have made a change which we believe will address this.
        Please try the next nightly build (June 23 or above) in the 5.0p or 5.1p branches.

        Regards
        Isomorphic Software

        Comment


          #5
          Thanks for the update. I'm trying it now, but I've run into a problem using the new jars. The core .js libraries aren't loading. In my host page I have <isc:loadISC skin="<%=skin %>" modulesDir="modules-debug/" includeModules='RichTextEditor,Calendar,FileLoader,Drawing,Charts' />

          I haven't changed that, or anything else, only replaced the old jars with the new one and did another GWT compile. Now I'm getting a 404 error when the browser tries to download the SGWT modules. Our project name is ipgui. An example URL is http://localhost:8080/ipgui/sc/modul..._2015-06-23.js

          I've found that if I copy the sc folder from it's normal location under war/ipgui and put a copy of it directly in the war directory the application loads, but then RPCs start to fail with 404s as well. For example; http://localhost:8080/ipgui/sc/IDACa...6-23&isc_xhr=1
          Last edited by jay.l.fisher; 23 Jun 2015, 09:25.

          Comment


            #6
            This seems likely to be an issue with your project configuration rather than a change to the framework libraries honestly. 404's on the SmartClient resources (the sc/ directory) typically imply a failure to import the appropriate module in your .gwt.xml file. 404's or similar for the IDACall servlet typically indicates a misconfigured web.xml file.
            Failures on both may indicate an incorrect or missing "isomorphicDir" in your bootstrap HTML file, or a typo etc such that resources are being looked for in the wrong place.

            Or of course this could be some strange Eclipse configuration / staleness type issue which would be resolved by doing a clean / removing unit-cache, clearing browser cache closing and rebooting everything, etc!

            Not much we can tell you beyond that unless you can show us how to actually cause this error and it definitely indicates a problem with the package.

            Regards
            Isomorphic Software

            Comment


              #7
              Somehow our app has been working in a variety of environments for the last couple of years without having the isomorphicDir variable set in our host html. It was in the very old original version, but we switched from using an index.html to an index.jsp a very long time ago and that line of javascript got missed in the process. Oddly enough, it was never a problem until updating to these new sgwt jars. Putting it back solved the problem and I am now able to run with the new jars.

              However, the original "Must be a date" problem is not fixed in the June 23 build. It seems to only be a problem with validation on the CanvasItem. Here is a dump of the CanvasItem, it's value and the validators on it. It is the isDate validator that is failing.
              Code:
              CanvasItem{eventParent: [DynamicForm ID:isc_DynamicForm_131],
              containerWidget: [DynamicForm ID:isc_DynamicForm_131],
              form: [DynamicForm ID:isc_DynamicForm_131],
              AUTOIDClass: "DeliveryTab_91",
              name: "handoverDate",
              editorType: "CanvasItem",
              shouldSaveValue: true,
              title: "First new Handover",
              required: true,
              showChooserWeekPicker: "true",
              columnCode: "76a305ab1fdbd76d6bc2ed5a826a8d33",
              type: "date",
              useTextField: "true",
              showChooserFiscalYearPicker: "true",
              validators: Array[2],
              ID: "isc_DeliveryTab_91_1",
              canvas: [DynamicForm ID:isc_DynamicForm_133],
              canvasInitialized: true}
              Evaluator: result of 'isc_DeliveryTab_91_1.getValue()...' (0ms):
              Mon Aug 01 00:00:00 GMT-500 2016

              Evaluator: result of 'isc_DeliveryTab_91_1.validators...' (1ms):
              [Obj{type:isDate}, Obj{type:required}]

              Again using Chrome debugger I can see that the value which was a LogicalDate is now just a Date (jsdate). It is the object.constructor check that fails.
              Code:
                  //>    @classMethod    isA.Date()
                  //
                  //    Is <code>object</code> a Date object?
                  //
                  //    @param    object    (object)    object to test
                  //    @return            (boolean)    true == <code>object</code> is a Date
                  //    @visibility external
                  //<
                  Date : function (object) {
                      if (object == null) return false;
                      if (object.constructor && object.constructor.__nativeType != null) {
                          return object.constructor.__nativeType == 3;
                      }
                      return (""+object.constructor) == (""+Date) &&
                              // if the Date constructor is passed a string it doesn't understand, it returns a
                              // sort of pseudo date object, which returns bad values from getYear(), etc.
                              object.getDate && isc.isA.Number(object.getDate());
                  },
              You can see by evaluating the two sides of the == comparison.
              ""+Date results in "function Date() { [native code] }"
              ""+object.constructor results in "function Object() { [native code] }"

              object = Date_4 {jsdate: Sun May 15 2016 12:00:00 GMT-0500 (CDT)}
              Last edited by jay.l.fisher; 24 Jun 2015, 10:52.

              Comment


                #8
                Ok - we'll run a sanity check on the fix and let you know what we find. We may ultimately need a test case.

                Regards
                Isomorphic Software

                Comment


                  #9
                  I found a workaround, but it seems like this could crop up in other situations where a CanvasItem is used to render a datasource field. In this case the field is type="date" which causes the CanvasItem to inherit the isADate validation. The value for the CanvasItem is being stored as a generic Object, which fails the IsADate test due to the constructor name being "Object" instead of "Date". I added this line to the CanvasItem's ShowValueHandler to re-store the value, casting it as a Date.
                  Code:
                  setValue((Date)event.getDataValue());
                  That seems to have fixed the problem, with no adverse side effects that I can see. Let me know if there is a better approach.

                  Comment


                    #10
                    We have retested our fix (testing against the latest 5.0 nightly build, Jun 24) and it appears to be working for our test case.

                    Here's the code we used to test this:
                    Code:
                    import com.google.gwt.core.client.EntryPoint;
                    import com.smartgwt.client.data.DataSource;
                    import com.smartgwt.client.data.DataSourceField;
                    import com.smartgwt.client.data.fields.DataSourceDateField;
                    import com.smartgwt.client.data.fields.DataSourceSequenceField;
                    import com.smartgwt.client.util.LogicalDate;
                    import com.smartgwt.client.util.SC;
                    import com.smartgwt.client.widgets.form.DynamicForm;
                    import com.smartgwt.client.widgets.form.fields.ButtonItem;
                    import com.smartgwt.client.widgets.form.fields.CanvasItem;
                    import com.smartgwt.client.widgets.form.fields.DateItem;
                    import com.smartgwt.client.widgets.form.fields.FormItem;
                    import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
                    import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
                    import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
                    import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
                    import com.smartgwt.client.widgets.form.fields.events.ShowValueEvent;
                    import com.smartgwt.client.widgets.form.fields.events.ShowValueHandler;
                    
                    public class LogicalDateIssueTest implements EntryPoint {
                    
                    	@Override
                    	public void onModuleLoad() {
                    		
                    		DataSource testDS = createTestDS();
                    
                    		DynamicForm testForm = new DynamicForm();
                    		testForm.setDataSource(testDS);
                    		FormItem field2Item = new CustomDateItem();
                    		field2Item.setName("field2");
                    		
                    		ButtonItem validateButton = new ButtonItem("Validate!");
                    		validateButton.addClickHandler(new ClickHandler() {
                    			
                    			@Override
                    			public void onClick(ClickEvent event) {
                    				event.getForm().validate();
                    			}
                    		});
                    		
                    		testForm.setItems(field2Item, validateButton);
                    		
                    		// Make it obvious
                    		testForm.setBackgroundColor("gold");
                    		
                    		testForm.draw();
                    		
                    	}
                    	
                    	private class CustomDateItem extends CanvasItem {
                    		DynamicForm innerForm;
                    		DateItem innerDateItem;
                    		CustomDateItem() {
                    			innerForm = new DynamicForm();
                    			innerForm.setNumCols(1);
                    			innerForm.setBorder("1px solid black");
                    
                    			innerDateItem = new DateItem("innerDate");
                    			innerDateItem.setShowTitle(false);
                    			
                    			innerDateItem.addChangedHandler(new ChangedHandler() {
                    				
                    				@Override
                    				public void onChanged(ChangedEvent event) {
                    					Object value = event.getValue();
                    					// Verify that it is indeed a Logical Date, and store it out...
                    					SC.logWarn("Value:" + value + " is a logical date?:" + (value instanceof LogicalDate));
                    					storeValue(value);
                    				}
                    			});
                    			
                    			innerForm.setItems(innerDateItem);
                    			
                    			addShowValueHandler(new ShowValueHandler() {
                    				
                    				@Override
                    				public void onShowValue(ShowValueEvent event) {
                    					innerDateItem.setValue(event.getDataValue());					
                    				}
                    			});
                    			
                    			setCanvas(innerForm);
                    			
                    		}
                    
                    	}
                    	
                    	private DataSource createTestDS() {
                    		DataSource testDS = new DataSource();
                    		
                    		DataSourceField field1 = new DataSourceSequenceField("field1");
                    		field1.setPrimaryKey(true);
                    		DataSourceField field2 = new DataSourceDateField("field2");
                    		
                    		testDS.setFields(field1, field2);
                    		
                    		testDS.setClientOnly(true);
                    		
                    		return testDS;
                    	}
                    
                    }
                    As you can see from the logged warning - the inner form's dateItem generates a LogicalDate instance - we're then passing that into storeValue on the CanvasItem and it is behaving as expected.

                    Probably the best way to proceed would be to take a look at this test case and see how it differs from your actual usage/ if possible tweak it to demonstrate the problem, so we can take another look

                    Regards
                    Isomorphic Software

                    Comment


                      #11
                      I haven't been able to recreate the problem by bringing your test code into my project, but in examining the resulting CanvasItem objects using the dev console I can see that there are a couple of key differences. In your working example the CanvasItem js obj has these two attributes that are not present in my CanvasItem.

                      _typeDefaultsAdded: true,
                      _simpleType: Obj{name:date}

                      Both have type: "date", but mine is missing the other two attributes. I don't know what I could be doing differently that could account for that difference, or whether those attributes are involved, but they seem to be related to the item's data type handling.

                      Comment


                        #12
                        Is your form bound to a DataSource, or is the "date" type on the field being specified in some other way (directly on the item)?

                        Can you put together a snippet of code similar to ours in the way it is runnable and self contained, but which better reflects the setup in your actual usage? This might reveal what the difference is?

                        Comment


                          #13
                          It is bound to a DataSource. The field definition is ...

                          <field name="handoverDate" nativeName="handDt" title="Handover" type="date" useTextField="true"/>

                          I'm still trying to modify your example to see what will cause it to fail in the way mine does and have had no luck yet.

                          Comment

                          Working...
                          X