2

I'm developing a mobile application with ionic framework and angularJS. Now I got problem when working on dynamic validation.

This is my form, I try to set validation value from controller when select box changed, but it won't work.

<form id="my-form" ng-submit="submit(form,request)" name="form" novalidate>
  <div ng-class="{'has-error':form.biller-name.$invalid}">
    <span>Biller</span>
    <select id="biller" name="biller-name" ng-model="request.biller" ng-change="getValidationAmount(request.biller)" required>
        <option value="">Choose biller name</option>
      <option value="BA">Biller A</option>
      <option value="BB">Biller B</option>
        <option value="BC">Biller C</option>
    </select>
    <div ng-show="form.biller-name.$invalid && form.biller-name.$dirty">
        <p ng-if="form.biller-name.$error.required">Biller name must be chosen</p>
    </div>
  </div>

  <div ng-class="{'has-error':form.amount.$invalid}">
    <span>Amount</span>
    <input name="amount" ng-model="request.amount" type="number" ui-number-mask="2" max="{{billerVal.maxAmount}}" min="{{billerVal.minAmount}}" required/>

    <div ng-show="form.amount.$invalid && form.amount.$dirty">
            <p ng-if="form.amount.$invalid">validation works</p>
    </div>
  </div>

  <div>
    <input value="Submit" id="login_btnSubmit" data-role="button"
    data-shadow="false" type="submit"/>
  </div>
</form>

My JS, have two function. first to get data from db, and the update function will be update validation on the page.

$scope.getValidationAmount = function (data){

  //get data from db
  beneficiaryService.getAmountByBenefeciaryType(JSON.parse(data)).then(function(amount){

    var amountSplitLast2Character = amount.substr(amount.length - 2);
    var firstCharacter = amount.substr(0, (amount.length - amountSplitLast2Character.length));
    $scope.bill.amount = firstCharacter+'.'+amountSplitLast2Character;

    //will do update function
    $scope.update(JSON.parse(data).nickname);
  },function(data,opt,error){});
};

$scope.update = function(nickname) {

  var billerVal = {};

  //this code below just for get object biller by nickname
  for(var i in billerList) {
    if (billerList[i].nickname == nickname) {
      for(var j in billerEnumList) {
        if (billerEnumList[j].key == billerList[i].name) {
          billerVal = billerEnumList[j];
        }
      }
    }
  }

  billerVal.maxAmount = parseInt(billerVal.maxAmount); //will return a number of amount e.g 100
  billerVal.minAmount = parseInt(billerVal.minAmount); //will return a number of amount e.g 1
  $scope.billerVal = billerVal; //set validation value to html page
}

When I hard coded validation for min and max value in html directly the validation works properly. But, when I try to use dynamic validation like code above, the validation won't works.

2 Answers 2

2

You can use a simple custom validation directive as a workaround for this particular condition displayed in this demo fiddle.

There are issues related to it in angular official Github Repo.

app.directive('ngMin', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, elem, attr, ctrl) {
            scope.$watch(attr.ngMin, function () {
                ctrl.$setViewValue(ctrl.$viewValue);
            });
            var minValidator = function (value) {
                var min = scope.$eval(attr.ngMin) || 0;
                if (!isEmpty(value) && value < min) {
                    ctrl.$setValidity('ngMin', false);
                    return undefined;
                } else {
                    ctrl.$setValidity('ngMin', true);
                    return value;
                }
            };

            ctrl.$parsers.push(minValidator);
            ctrl.$formatters.push(minValidator);
        }
    };
});

app.directive('ngMax', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, elem, attr, ctrl) {
            scope.$watch(attr.ngMax, function () {
                ctrl.$setViewValue(ctrl.$viewValue);
            });
            var maxValidator = function (value) {
                var max = scope.$eval(attr.ngMax) || Infinity;
                if (!isEmpty(value) && value > max) {
                    ctrl.$setValidity('ngMax', false);
                    return undefined;
                } else {
                    ctrl.$setValidity('ngMax', true);
                    return value;
                }
            };

            ctrl.$parsers.push(maxValidator);
            ctrl.$formatters.push(maxValidator);
        }
    };
});

Hope this helps.

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

3 Comments

Why create a directive? min and max is already a built in directive from the core angular as stated in the angular docs
Because its a bug that angular do not watches these built in directives after it is rendered dynamically.There are issues related to it in angular official github repo. So this is a workaround.
Thank you @mJunaidSalaat will try to use your directive and will mark as accepted aswer after all work.
0

You don't need to use interpolation syntax to indicate the min and max length in the view. You could directly use the $scope property.

<input name="amount" ng-model="request.amount" type="number" ui-number-mask="2" max="billerVal.maxAmount" min="billerVal.minAmount" required/>

5 Comments

It wouldn't work. with interpolation syntax I got the value filled to the min and max value, but not without it.
Are you sure that the billerVal object is being populated correctly?
Sure, this is with interpolation syntax http://postimg.org/image/5bl2vctkp/ and this one without http://postimg.org/image/aa3zw57zt/
Where is the interpolation in the 1st image? interpolation is {{}}. Of course on the first image it will work as you've hard coded the actual value. If I were you, try to display the billerVal object in the view for you to see the actual values when the update() function is called.
yes I know the interpolation is {{}}. at the first image that is syntax using interpolation, and when I change select box, it will populate by self data from update function. but no if I don't use interpolation.

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.