Aloha. I have two fields for time input, start + end. I've created custom validations to check if field is blank, valid time, and start is before end time. Works except for the following:
- edit both times to be 7:45 and 7:50 respectively, no errors;
- edit end time to be before the start time, from 7:50 to 7:44, the validation does its job, i.e. $error.validAfter = true;
- ignore end time field and edit start time to be after the end time, from 7:45 to 7:47, ($error.validBefore error = true);
- edit start time to be before end time, from 7:47 to 7:43 - $error.validBefore = false;
At this point, $error.validAfter is still true for end time. Is there a way to update this after the validation for start time, fourth bullet, has been confirmed?
HTML:
<div data-ng-app="scheduleApp">
<h2>{{ "Schedule App" }}</h2>
<div class="time" data-ng-form="formtime">
<div class="form-row">
<span class="label">Start time:</span>
<span class="field">
<input type="text" name="startTime" ng-model="startTime" is-from placeholder="e.g. 7:50" required validatetime="{{ endTime }}" />
<span class="error" ng-class="{required: formtime.startTime.$error.required, invalid: formtime.startTime.$error.validTime}">enter a valid time, <i>hh:mm</i></span>
<span class="error" ng-show="formtime.startTime.$error.validBefore" ng-class="{invalid: formtime.startTime.$error.validBefore && !formtime.startTime.$error.validTime}">start time must be before the end time</span>
</span>
<span>{{ formtime.startTime.$error }}</span>
</div>
<div class="form-row">
<span class="label">End time:</span>
<span class="field">
<input type="text" name="endTime" ng-model="endTime" placeholder="e.g. 7:55" required validatetime="{{ startTime }}" />
<span class="error" ng-class="{required: formtime.endTime.$error.required, invalid: formtime.endTime.$error.validTime}">enter a valid time, <i>hh:mm</i></span>
<span class="error" ng-show="formtime.endTime.$error.validAfter" ng-class="{invalid: formtime.endTime.$error.validAfter && !formtime.endTime.$error.validTime}">end time must be after the start time</span>
</span>
<span>{{ formtime.endTime.$error }}</span>
</div>
</div>
Javascript:
var app = angular.module("scheduleApp", []);
function PMhour(hour) {
var pmHours = [1,2,3,4,5,6];
return pmHours.indexOf(hour) >= 0 ? (hour + 12) : hour;
}
app.directive("validatetime", function() {
return {
restrict: "A"
, require: "ngModel"
, link:
function($scope, elem, attrs, ctrl) {
var validTime = false;
var validCompare = false;
var isFrom = attrs.isFrom == null ? false : true;
var otherTime;
attrs.$observe("validatetime", function(otherTimeVal) {
otherTime = otherTimeVal;
});
ctrl.$parsers.unshift (isValidTime, isValidTimeCompare);
ctrl.$formatters.unshift(isValidTime, isValidTimeCompare);
function isValidTime(value) {
var regex = /^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/i;
validTime = false;
if (value != null) {
if (value.length) {
validTime = regex.test(value);
}
}
ctrl.$setValidity('validTime', validTime);
if (validTime) {
return value;
}
}
function isValidTimeCompare(value) {
var tmpFrom;
var tmpTo;
if (otherTime) {
validCompare = (otherTime.length == 0);
}
else {
validCompare = true;
}
if (validTime) {
if (otherTime.length) {
if (isFrom) {
tmpTo = new Date(2000, 0, 1, PMhour(parseInt(otherTime.split(":")[0])), parseInt(otherTime.split(":")[1]));
tmpFrom = new Date(2000, 0, 1, PMhour(parseInt(value.split(":")[0])) , parseInt(value.split(":")[1]));
}
else {
tmpFrom = new Date(2000, 0, 1, PMhour(parseInt(otherTime.split(":")[0])), parseInt(otherTime.split(":")[1]));
tmpTo = new Date(2000, 0, 1, PMhour(parseInt(value.split(":")[0])) , parseInt(value.split(":")[1]));
}
validCompare = (tmpFrom < tmpTo);
}
}
if (isFrom) {
ctrl.$setValidity("validBefore", validCompare); // from is before the other time
}
else {
ctrl.$setValidity("validAfter", validCompare); // to is after the other time
}
return value;
};
}
}
});
Plunker here: http://plnkr.co/edit/Innbv6lCYewefSgKhvGA?p=info
Sorry, I'm new to the plunker concept. Let me know if you cannot see the code. Mahalo for your assistance.