Details
-
Type: Bug
-
Status: In Quality Assurance
-
Priority: Minor
-
Resolution: Unresolved
-
Affects Version/s: 4.7.14
-
Fix Version/s: 4.7.17
-
Component/s: Core CiviCRM
-
Labels:
-
Versioning Impact:Patch (backwards-compatible bug fixes)
-
Documentation Required?:None
-
Funding Source:Contributed Code
-
Verified?:No
Description
Discovered when building an Angular form in an extension: form.$error should report that a datepicker field with only the date supplied is invalid. It does not.
Ramifications: Contrary to developers' expectations, users will be able to click a submit button marked up like this:
<button ng-click="doSave()" ng-disabled="form.$invalid">Go!</button>
To reproduce, build a simple form using the crmUiDatepicker directive and a button like the one above. Make the datepicker required. Selecting a date should not cause the button to become enabled, but it does. While the required validator is satisfied (since the model has a value), the incompleteDateTime validator should not be, since the time component is required unless invoked as follows:
<crm-ui-datepicker={time: false} />
There's other paradoxical behavior here too. If you then enter a time, the button is disabled, though one would it expect it to be enabled. Editing the time a second time results in the expected behavior, which is that the button is enabled.
Fundamentally, the problem is that the directive is not properly alerting the form to its valid/invalid state. It appears to be an order-of-operations problem. In the original code, the field was flagged as valid/invalid on the change event. I posit that the change event on the element fires after whatever event is responsible for updating the form state from the field states, which explains why the form state always seems to be one user interaction behind as relates to the datepicker widget. My proposed patch puts the same logic in a validator on the controller.