Vibhanshu
Vibhanshu

Reputation: 542

Dynamic validation in AngularJS

I have a field in form which is to be validated depending upon the value of some other field. To achieve that I have created a validation directive.

More specifically I have a group of two radio buttons and a text field, which is to be validated, against the chosen radio button.

If first radio button is chosen, text-fields value can be 0-100 If second radio button is chosen, text-fields value can be 0-infinite

I pass the value of chosen radio-button to directive and depending upon that condition is checked for validation of text field's value.

So far so good. Things work fine for the scenario except for some edge cases.

For example if initially second radio button is chosen, then if you write 400 in text field and then choose first radio button. It doesn't show invalid field.

directive('discountValidator', function () {
return {
  require: 'ngModel',
  scope: {
    discountValidator: '='
  },
  link: function (scope, attr, elem, ngModel) {
    ngModel.$validators.discount = function (modelvalue) {
      return scope.discountValidator.toLowerCase() === 'flat' ? modelvalue >= 0 : (modelvalue >= 0 && modelvalue <= 100);
    };
  }
};

});

html

<md-input-container class="md-block">
      <md-radio-group ng-model="vm.type" layout>TYPE&nbsp;
        <md-radio-button value="PERCENT" checked>%</md-radio-button>
        <md-radio-button value="FLAT">Flat</md-radio-button>
      </md-radio-group>
    </md-input-container>

    <!-- Discount Amount Field-->
    <md-input-container class="md-block">
      <input type="number" name="discountAmt" ng-model="vm.value" required discount-validator="vm.type">

      <!-- Error Messages -->
      <div ng-messages="form1.discountAmt.$error" ng-if="form1.$submitted || form1.discountAmt.$touched">
        <div class="error" ng-message="required">Required</div>
        <div class="error" ng-message="discount">Invalid Discount</div> 
      </div>
    </md-input-container>

  </div>

function DiscountValidator() {
    return {
      require: 'ngModel',
      scope: {
        discountValidator: '='
      },
      link: function (scope, attr, elem, ngModel) {
        ngModel.$validators.discount = function (modelvalue) {
          return scope.discountValidator.toLowerCase() === 'flat' ? modelvalue >= 0 : (modelvalue >= 0 && modelvalue <= 100);
        };
      }
    };
  }

var app = angular.module('app', ['ngMessages', 'ngMaterial'])
      .controller('mainCtrl', function($scope){  
        var vm = this;
        vm.onSubmit = function(form) {

        };
        
        vm.type='PERCENT';
      })
    .directive('discountValidator', DiscountValidator);
<!DOCTYPE html>
<html ng-app='app'>
<head>
<meta name="description" content="Dynamic validation in AngularJs">
   <!-- Angular Material style sheet -->
  <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/1.1.0-rc2/angular-material.min.css">
    
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>



<body ng-controller='mainCtrl as vm'>
  <md-content>
    <form name="form1" ng-submit="vm.onSubmit(addressForm)" novalidate>
      <div layout="column">

        <md-input-container class="md-block">
          <md-radio-group ng-model="vm.type" layout>TYPE&nbsp;
            <md-radio-button value="PERCENT" checked>%</md-radio-button>
            <md-radio-button value="FLAT">Flat</md-radio-button>
          </md-radio-group>
        </md-input-container>

        <!-- Discount Amount Field-->
        <md-input-container class="md-block">
          <input type="number" name="discountAmt" ng-model="vm.value" required discount-validator="vm.type">

          <!-- Error Messages -->
          <div ng-messages="form1.discountAmt.$error" ng-if="form1.$submitted || form1.discountAmt.$touched">
            <div class="error" ng-message="required">Required</div>
            <div class="error" ng-message="discount">Invalid Discount</div> 
          </div>
        </md-input-container>

      </div>

      <md-button type='submit' class='md-primary'>Submit</button>
    </form>
  </md-content>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-animate.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-aria.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-messages.min.js"></script>

  <!-- Angular Material Library -->
  <script src="https://ajax.googleapis.com/ajax/libs/angular_material/1.1.0-rc2/angular-material.min.js"></script>

  
</body>
</html>

Upvotes: 1

Views: 148

Answers (1)

SeRu
SeRu

Reputation: 314

Since my comment solved the problem I'll post it as answer. The simplest solution for the example would be to clear the input field if the radio button is changed.

Upvotes: 1

Related Questions