Validating Start/End dates in AngularJS

In this scenario, the user is prompted for starting/ending dates. Ideally these are validated as the user is filling out the form (rather than on submit). However the co-dependence between different fields makes directive use difficult. I was interested in a simple fix. So sorry, this is not too portable. But it’s simple and works.

I’m using the Angular Bootstrap date picker control.

Note that the way I’ve set this up, it piggybacks on my date validation method. See my separate post about this. If you don’t use this method, you’ll need to choose some other way to make sure both dates are valid before comparing them!

In the controller:

$scope.$watch('model.Template.StartDate', validateDates);
$scope.$watch('model.Template.EndDate', validateDates);

function validateDates() {
    if (!$scope.model) return;
    if ($scope.form.startDate.$error.invalidDate || $scope.form.endDate.$error.invalidDate) {
        $scope.form.startDate.$setValidity("endBeforeStart", true);  //already invalid (per validDate directive)
    } else {
        //depending on whether the user used the date picker or typed it, this will be different (text or date type).  
        //creating a new date object takes care of that.  
        var endDate = new Date($scope.model.Template.EndDate);
        var startDate = new Date($scope.model.Template.StartDate);
        $scope.form.startDate.$setValidity("endBeforeStart", endDate >= startDate);
<form name="myForm">
    <input id="startDate" type="text" valid-date datepicker-popup="MM/dd/yyyy" ng-model="model.Template.StartDate" name="startDate" ng-required="true" />

    <input id="endDate" type="text" valid-date datepicker-popup="MM/dd/yyyy" ng-model="model.Template.EndDate" name="endDate" ng-required="true" />

    <span ng-show="form.startDate.$error.endBeforeStart">End date must be on or after start date.</span>

    <span ng-show="form.startDate.$error.invalidDate || form.endDate.$error.invalidDate">Check dates for validity</span>
    <span ng-show="form.startDate.$error.required || form.endDate.$error.required">A required date is missing</span>

Another thing you might notice is that we (arbitrarily) attach the error to the start date. For this purpose, it doesn’t matter where we put the error, as long as it’s on the form somewhere. You can’t attach an error directly to the form itself, but an error on any field will invalidate the form.