-1

i have a form that uses Jquery validation engine as a validation library inside and Angular's SPA. The form has a check box and a text-box . i want that text-box should be required only if the check box is checked. this functionality seems to be working. but the problem is that my ng-submit function gets called even if there is a validation error.I want to restrict this call. i am using Angular's directive to validate and invalidate the controls.

            <form role="form" name="frmVariableConfig1" class="formValidVariableConfig1 form-inline" novalidate ng-submit="frmVariableConfig1.$valid && vm.saveChanges()">


                        <span class="checkableBox"><input type="checkbox" item="variable" toggle-selection="toggleSelection('1')" bootstrap-check ng-model="vm.SetThreshold"></span>


            <input type="text" ng-model="vm.Threshold" name="cntrlThresh" class="form-control input-sm {{ vm.getValidation(vm.SetThreshold) }}" placeholder="Threshold" check-validation2>

                  <button type="submit" class="btn btn-sm">Save</button>
        </form>   

vm.getValidation function returns "validate[required]" or "" as per the value of vm.SetThreshold which is the model of the check-box above.

directive is set like this

    .module('app').directive('checkValidation2', [
    function () {
        return {
            restrict: 'A',
            require: '?ngModel',
            link: function (scope, element, attrs, ngModel) {
                element.closest('form').validationEngine();

                scope.$watch(attrs.ngModel, function (newValue, oldValue) {
                    var valid = !element.validationEngine('validate');//check if the control is valid
                    ngModel.$setValidity(element.context.name, valid); //set validity accordingly. 
                    return valid;
                });
            }
        };
    }
]);

UPDATE

here is something that might help. on page load the form is ng-valid. fine because there is no validation injected in the text box..now i click the check box it injects the validation class in the text box but the form remains unchanged. i.e. it is still ng-valid. so now if i click the button cause form is valid the function is called.

and if i simply add validation class without the function call the form is invalid on page load and gets valid if the text box is filled. which is the expected behavior.

its looks like all is happening because i am injecting the validation dynamically. some how forms validations needs to be restarted after injection.

checkBox is using iCheck Plugin with a directive

angular.module('app').directive('checkValidation2', ['$compile',
function($compile) {
    return {
        restrict: 'A',
        require: '?ngModel',
        compile: function(ele, attr, ngModel) {
            ele.closest('form').validationEngine();
            //removing directive attribute to stop to go it to infinite loop
            //as we are compiling DOM again

            ele.removeAttr("check-Validation2");
            var compile = $compile(ele); //compiling object on prelink state
            return function(scope, element, attrs, ngModel) {
                compile(scope); //compiling dom in postlink phase
                scope.$watch(attrs.ngModel, function(newValue, oldValue) {
                    var valid = !element.validationEngine('validate'); //check if the control is valid
                    ngModel.$setValidity(element.context.name, valid); //set validity accordingly. 
                    return valid;
                });
            }

        }
    };
}

]);

Raas Masood
  • 1,475
  • 3
  • 23
  • 61

1 Answers1

0

As you are using controllerAs syntax your value is not inside a scope you need to bind that value inside a scope

$scope.$watch(angular.bind(this, function () {
    return this[attrs.ngModel]; // this will evaluate ng-model value from `this`
}), function (newVal, oldVal) {
     var valid = !element.validationEngine('validate');//check if the control is valid
     ngModel.$setValidity(element.context.name, valid); //set validity accordingly. 
     return valid;
});

Update

You should try to inject form validationEngineat compilation phase of the directive so that the changes will occur accurately in the DOM,

Directive

.module('app').directive('checkValidation2', [
    function() {
        return {
            restrict: 'A',
            require: '?ngModel',
            compile: function(ele, attr, ngModel) {
                ele.closest('form').validationEngine();
                //removing directive attribute to stop to go it to infinite loop
                //as we are compiling DOM again
                ele.removeAttr('checkValidation2');
                var compile = $compile(ele); //compiling object on prelink state
                return function(scope, element, attrs, ngModel) {
                    compile(scope); //compiling dom in postlink phase
                    scope.$watch(attrs.ngModel, function(newValue, oldValue) {
                        var valid = !element.validationEngine('validate'); //check if the control is valid
                        ngModel.$setValidity(element.context.name, valid); //set validity accordingly. 
                        return valid;
                    });
                }

            }
        };
    }
]);
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
  • Yes its as syntax. Will test it in a min – Raas Masood Jun 09 '15 at 18:22
  • i understood your point but the result is same. validation does get applied like before but it still calls my function means the form remain ng-valid how ever if i dont inject validation classes from a function, vm.getValidation, it works as expected. – Raas Masood Jun 09 '15 at 18:41
  • @RaasMasood does your watch is returning proper value? and validity is setting properly?\ – Pankaj Parkar Jun 09 '15 at 18:54
  • i get Maximum call stack size exceeded – Raas Masood Jun 10 '15 at 16:10
  • you need to remove directive element before compiling elenent..seems like currently it directive element infinitely and throwing maximum call stack exceed error – Pankaj Parkar Jun 10 '15 at 16:16
  • isnt ele.removeAttr('checkValidation2'); removing it ? – Raas Masood Jun 10 '15 at 16:18
  • could you place debugger their and check it does does that really removing it..I doubt about that – Pankaj Parkar Jun 10 '15 at 16:23
  • removeAttr doesn't seems to be working. i checked the outer HTML after removeAttr and the attrib is still there. – Raas Masood Jun 10 '15 at 16:31
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/80203/discussion-between-pankajparkar-and-raas-masood). – Pankaj Parkar Jun 10 '15 at 16:35
  • My project is a SPA it has lots of plugging and scripts and other plugin files that it wasn't able to setup up a plunkr properly. Although i have setup a sperate project took out all necessary things and only required css js and html files with initial angular structure in place. main page has only this form and related controller file has controller code and all related directives. will you be able to take a look if i upload it on github? – Raas Masood Jun 11 '15 at 19:14
  • give me the details which plugins you are using..I'll try to create a plunkr by my own.. – Pankaj Parkar Jun 11 '15 at 19:20
  • "icheck" for check box "jquery validation engine" for validation – Raas Masood Jun 11 '15 at 19:23
  • after lot of trouble i created this properly working plunker and my overall issue is described here. ill be really great-full if you could take a look.http://stackoverflow.com/questions/30854264/angular-forms-validation-issues-when-using-plugins – Raas Masood Jun 15 '15 at 20:25
  • looking at it..Thanks :) – Pankaj Parkar Jun 16 '15 at 19:15