Skip to content
This repository has been archived by the owner on Jun 14, 2018. It is now read-only.

Commit

Permalink
fix(datepicker): $dirty and $touched handling for uif-datepicker
Browse files Browse the repository at this point in the history
Added support for `$touched` property on ngModel.
Fixed issue with `$dirty` being set on ngModel when initial value was bound to the model.

Closes #377. Closes #410.
  • Loading branch information
jjczopek authored and andrewconnell committed Nov 23, 2016
1 parent 96ecdc9 commit 620aeb9
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 10 deletions.
70 changes: 70 additions & 0 deletions src/components/datepicker/datepickerDirective.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,4 +258,74 @@ describe('datepicker: <uif-datepicker />', () => {

}));

it('Should not set $dirty on ngModel initially', inject(($compile: Function, $rootScope: ng.IRootScopeService) => {
let $scope: any = $rootScope.$new();
$scope.value = new Date(2016, 3, 2);

let datepicker: JQuery = $compile('<uif-datepicker ng-model="value"></uif-datepicker>')($scope);
$scope.$digest();

// initially should not be disabled
let ngModel: ng.INgModelController = angular.element(datepicker).controller('ngModel');

expect(ngModel.$dirty).toBeFalsy();
}));

it('Should not set $touched on ngModel initially', inject(($compile: Function, $rootScope: ng.IRootScopeService) => {
let $scope: any = $rootScope.$new();
$scope.value = new Date(2016, 3, 2);

let datepicker: JQuery = $compile('<uif-datepicker ng-model="value"></uif-datepicker>')($scope);
$scope.$digest();

// initially should not be disabled
let ngModel: ng.INgModelController = angular.element(datepicker).controller('ngModel');

expect(ngModel.$touched).toBeFalsy();
}));

it('Should set $dirty on ngModel when date changed', inject(($compile: Function, $rootScope: ng.IRootScopeService) => {
let $scope: any = $rootScope.$new();
$scope.value = new Date(2016, 3, 2);

let datepicker: JQuery = $compile('<uif-datepicker ng-model="value"></uif-datepicker>')($scope);
$scope.$digest();

datepicker = jQuery(datepicker[0]);

let goToday: JQuery = datepicker.find('.ms-DatePicker-goToday');
expect(goToday.length).toBe(1, 'Go to today should be present');
goToday.triggerHandler('click');
$scope.$digest();

expect(new Date($scope.value).getUTCDate()).toBe(new Date().getDate(), 'Day Today');
expect(new Date($scope.value).getUTCMonth()).toBe(new Date().getMonth(), 'Month Today');
expect(new Date($scope.value).getUTCFullYear()).toBe(new Date().getFullYear(), 'Year Today');

let ngModel: ng.INgModelController = angular.element(datepicker).controller('ngModel');

expect(ngModel.$dirty).toBeTruthy();

}));

it('Should set $touched on ngModel when datepicker opened', inject(($compile: Function, $rootScope: ng.IRootScopeService) => {
let $scope: any = $rootScope.$new();
$scope.value = new Date(2016, 3, 2);

let datepicker: JQuery = $compile('<uif-datepicker ng-model="value"></uif-datepicker>')($scope);
$scope.$digest();

datepicker = jQuery(datepicker[0]);

let textField: JQuery = datepicker.find('.ms-TextField-field');
expect(textField.length).toBe(1, 'Input should be present');
textField.triggerHandler('click');
$scope.$digest();

let ngModel: ng.INgModelController = angular.element(datepicker).controller('ngModel');

expect(ngModel.$touched).toBeTruthy();

}));

});
31 changes: 21 additions & 10 deletions src/components/datepicker/datepickerDirective.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,18 @@ export class DatepickerController {
picker.on({
open: function (): void {
self.scrollUp();

if (ng.isDefined(ngModel) && ngModel !== null) {
ngModel.$setTouched();
}

self.$scope.$apply();
},
set: function (value: string): void {
let formattedValue: string = picker.get('select', 'yyyy-mm-dd');
ngModel.$setViewValue(formattedValue);
if (ng.isDefined(ngModel) && ngModel !== null) {
ngModel.$setViewValue(formattedValue);
}
}
});
}
Expand Down Expand Up @@ -391,16 +399,19 @@ export class DatepickerDirective implements ng.IDirective {
let ngModel: ng.INgModelController = ctrls[1];

datepickerController.initDatepicker(ngModel);
ngModel.$render = function (): void {
if (ngModel.$modelValue !== '' && typeof ngModel.$modelValue !== 'undefined') {
if (typeof ngModel.$modelValue === 'string') {
let date: Date = new Date(ngModel.$modelValue);
datepickerController.setValue(date);
} else {
datepickerController.setValue(ngModel.$modelValue);
if (ng.isDefined(ngModel) && ngModel !== null) {
ngModel.$render = function (): void {
if (ngModel.$modelValue !== '' && typeof ngModel.$modelValue !== 'undefined') {
if (typeof ngModel.$modelValue === 'string') {
let date: Date = new Date(ngModel.$modelValue);
datepickerController.setValue(date);
} else {
datepickerController.setValue(ngModel.$modelValue);
}
ngModel.$setPristine();
}
}
};
};
}
}
}

Expand Down
46 changes: 46 additions & 0 deletions src/components/datepicker/dirtyDemo/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>

<head>
<script data-require="angularjs@1.5.5" data-semver="1.5.5" src="https://code.angularjs.org/1.5.5/angular.js"></script>
<link rel="stylesheet" href="https://appsforoffice.microsoft.com/fabric/1.0/fabric.min.css">
<link rel="stylesheet" href="https://appsforoffice.microsoft.com/fabric/1.0/fabric.components.min.css">
<!-- jquery (pickadate depends on jquery) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<!-- pickadate library -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/pickadate.js/3.5.6/compressed/picker.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pickadate.js/3.5.6/compressed/picker.date.js"></script>
<script src="../../../../dist/ngOfficeUiFabric.js"></script>
</head>

<body ng-app="app" ng-controller="AppController as vm">
<h1>Dirty Checking with ngOfficeUiFabric directives</h1>


<form name="dirtyForm" novalidate>

<input type="text" name="working" ng-model="vm.working" />

<uif-datepicker ng-model="vm.value" name="notWorking"></uif-datepicker>

<pre> {{ dirtyForm | json }}</pre>

</form>



<script>
angular.module('app', ['officeuifabric.core', 'officeuifabric.components', ]);

angular.module('app').controller('AppController', ['$scope', function() {
var vm = this;

vm.notWorking = "not working";
vm.working = "standard input element";

vm.value = new Date(2016, 3, 2);
}]);
</script>
</body>

</html>

0 comments on commit 620aeb9

Please sign in to comment.