javascriptangularjsangularjs-validation

Date validation in AngularJS


I cannot allow future date in my form built in angularjs

Here is my HTML:

<div ngCloak ng-app="laurelMoney" ng-controller="myCtrl">
  <form name="userForm">
    <div class="form-group">
      <input type='date' id="trandate" class="form-control" ng-model="trandate" required ng-class="{ 'has-error' : userForm.trandate.$error }" />
      <p ng-show="userForm.trandate.$error" class="help-block">Transaction can't be in future</p>
    </div>

    <a href="#" class="btn btn-primary btn-sm btn-block" ng-click="submitForm()" type="submit">Add Transaction</a>
  </form>

And my javascript isÑ

angular.module('laurelMoney', [])
  .controller('myCtrl', function($scope) {
    var today = new Date();
    var dd = today.getDate();
    var mm = today.getMonth() + 1;
    var yyyy = today.getFullYear();
    if (dd < 10) {
      dd = '0' + dd
    }
    if (mm < 10) {
      mm = '0' + mm
    }
    today = yyyy + '-' + mm + '-' + dd;
    document.getElementById("trandate").setAttribute("max", today);
    $scope.submitForm = function() {

      if ($scope.userForm.$valid) {
        alert('our form is amazing');
      } else {
        console.log("Error");
      }

    };
  });

This is working fine when the calendar pops up. Future dates are all disabled. but i am able to manually change it to a future date in the date input box.

System is allowing submit for future dates also. How to go about this??

Plunker

Thanks.


Solution

  • Well, from what I could understand from your question you're simply trying to throw a error message or disallow user to select a future date, is it right? So, here you go:

    Notes:

    1. Your Angular version in plunker is completely outdated, so it may not work as you expected;
    2. ngCloak should be ng-cloak;
    3. You should add name attribute in your input to validate it;
    4. Also, you could use ngSubmit to submit form, instead of ng-click.
    5. As pointed out in comments, you can disable button if the form is invalid, rather than make this check in controller;
    6. Finally, to set a date as max date (in your case today), you just have to do the following: $scope.max = new Date() and call it in your view;

    Here's an complete example:

    (function() {
      'use strict';
    
      angular
        .module('laurelMoney', [])
        .controller('myCtrl', myCtrl);
    
      myCtrl.$inject = ['$scope'];
    
      function myCtrl($scope) {
        $scope.max = new Date();
      }
    })();
    <!DOCTYPE html>
    <html>
    
    <head>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
      <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
    </head>
    
    <body ng-app="laurelMoney">
      <div ng-cloak ng-controller="myCtrl">
        <form name="userForm" novalidate ng-submit="submitForm()">
          <div class="form-group" ng-class="{ 'has-error' : userForm.trandate.$error }">
            <input type="date" name="trandate" class="form-control" required max="{{max}}" ng-model="trandate">
            <p ng-if="userForm.trandate.$touched && userForm.trandate.$error.required" class="help-block">Transaction is required</p>
            <p ng-if="userForm.trandate.$error.date" class="help-block">Transaction should be a valid date</p>
            <p ng-if="userForm.trandate.$error.max" class="help-block">Transaction can't be in future</p>
          </div>
          <button type="submit" class="btn btn-primary btn-sm btn-block" ng-disabled="userForm.$invalid">Add Transaction</button>
        </form>
        <pre ng-bind="userForm.trandate.$error | json"></pre>
      </div>
    </body>
    
    </html>