N.Khalifa
N.Khalifa

Reputation: 35

Angular check duplication input

I'm trying to validate a form where there are no duplication of values. I have a site contain a list of Ip adress. In my from the is possible to add many adresses but they should be unique.

HTML:

<div class="col-sm-6">
    <ul style="list-style-type: none;-webkit-padding-start: 0px;margin-bottom:0px">
    <li ng-repeat="ip in site.ips  track by $index | orderBy: '+ip.ip_adress'"  style="margin-bottom:0px">
        <ng-form name="ipForm">                     
        <div class="input-group" style="margin-top:5px" ng-class="{ 'has-error' : !ipForm.ip_adress.$error.duplicate && ipForm.ip_adress.$invalid && !ipForm.ip_adress.$pristine  }">
          <input type="text" class="form-control input-sm" name="ip_adress" 
          ng-pattern='/^([0-9]{1,3})[.]([0-9]{1,3})[.]([0-9]{1,3})[.]([0-9]{1,3})$/' 
          style="display: inline;" 
          ng-model="ip.ip_adress"
          placeholder="{{translate('config.sites.msg.site.ip.adress')}}"                    
          required />
            <div class="input-group-addon">
                <i class="glyphicon glyphicon-remove-circle" ng-click="removeIp(site, ip, $index)"></i>
            </div>
        </div>
        </ng-form>

    </li>
    </ul>   
</div>

I also tried with ng-change:"verifyDuplicate()" and here is the JS

$scope.verifyDuplicate = function() {
               var sorted, i;
                sorted = $scope.sites[0].ips.sort(function (a, b) {
                    if (a.ip_adress > b.ip_adress) return 1;
                    if (a.ip_adress < b.ip_adress) return -1;
                    return 0;
                });
                for(i = 0; i < $scope.sites.ips.length; i++) {
                    sorted[i].isDuplicate = ((sorted[i-1] && sorted[i-1].ip_adress == sorted[i].ip_adress) || (sorted[i+1] && sorted[i+1].ip_adress == sorted[i].ip_adress));
                }


            }

and this throw an error: Cannot read property 'ips' of undefined. I also tried this example but it doesnt work.

Any suggestions please ?

Upvotes: 1

Views: 1054

Answers (1)

developer033
developer033

Reputation: 24874

You must build a directive if you want to control the validity of your inputs, then your form will become $invalid.

Here's a simple demo that you can replicate in your code:

angular.module('app', ['ngMessages'])
  .controller('mainCtrl', function($scope) {
    $scope.site = {};
    $scope.site.ips = ['172.16.254.1', '255.255.255.255', '111.111.111.111']
  })

  .directive('duplicate', function() {
    return {
      restrict: 'A',
      scope: {
        index: '@',
        array: '@'
      },
      require: 'ngModel',
      link: function(scope, element, attrs, ngModel) {
        if (!ngModel) return;

        scope.$watch(function() {
            return ngModel.$modelValue
          },
          function() {
            validate();
          });

        var validate = function() {
          scope.array = JSON.parse(scope.array);
          var elem_value = element.val();
          var obj = scope.array.find(function(value, i) {
            return value == elem_value && scope.index != i;
          });
          ngModel.$setValidity('duplicate', obj ? false : true);
        };
      }
    }
  });
<!DOCTYPE html>
<html ng-app="app">

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" />
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-messages/1.5.7/angular-messages.min.js"></script>
</head>

<body ng-controller="mainCtrl">
  <div class="col-sm-6">
    <ul style="list-style-type: none;-webkit-padding-start: 0px;margin-bottom:0px">
      <li ng-repeat="ip in site.ips track by $index" style="margin-bottom:0px">
        <ng-form name="ipForm">
          <div class="input-group" style="margin-top:5px" ng-class="{ 'has-error' : ipForm.ip_address.$invalid }">
            <input type="text" name="ip_address" class="form-control input-sm" ng-pattern='/^([0-9]{1,3})[.]([0-9]{1,3})[.]([0-9]{1,3})[.]([0-9]{1,3})$/' style="display: inline;" ng-model="site.ips[$index]" placeholder="{{translate('config.sites.msg.site.ip.adress')}}"
            required duplicate index="{{$index}}" array="{{site.ips}}" />
            <div class="input-group-addon">
              <i class="glyphicon glyphicon-remove-circle" ng-click="removeIp(site, ip, $index)"></i>
            </div>
            <div class="help-block" ng-messages="ipForm.ip_address.$error" ng-if="ipForm.ip_address.$touched">
              <p ng-message="required">This field is required</p>
              <p ng-message="minlength">This field is too short</p>
              <p ng-message="maxlength">This field is too long</p>
              <p ng-message="pattern">This needs to be a valid ip</p>
              <p ng-message="duplicate">Duplicate!</p>
            </div>
          </div>
        </ng-form>
      </li>
    </ul>
  </div>
</body>

</html>

Note: It's just to point you to the right direction, maybe it isn't the most efficient way to do this.

Anyway I hope it helps.

Upvotes: 1

Related Questions