1

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 ?

3
  • can u show the structure of $scope.sites Commented Jul 16, 2016 at 18:25
  • in form (html) you use site.ips as source (site.ips supposed to be array) and in verifyDuplicate you use sites[0] (sites supposed to be array). This should match. Try $scope.site.ips[0] in js Commented Jul 16, 2016 at 18:27
  • 1
    Besides you've a lot of errors in your code, if you want to set validate of $duplicate you must use a directive, otherwise the form will keeps valid. Commented Jul 16, 2016 at 18:50

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.