Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CheckValid not working as expected #286

Open
codeuniquely opened this issue Jul 1, 2017 · 3 comments
Open

CheckValid not working as expected #286

codeuniquely opened this issue Jul 1, 2017 · 3 comments

Comments

@codeuniquely
Copy link

codeuniquely commented Jul 1, 2017

when i call to check valid

this.checkValid = function(form) {
   return !!(form && form.$valid);
};

Here . form.$valid = undefined

This is because i have an OPTIONAL control (user does not have to fill it in), but if they do it has a regEx validation.

so this input on the form also has a $valid = undefined - because the user NEVER entered the input and just skipped that part of the form.

The control is still ng-valid, the form is ng-valid (all inputs) - and none of the error messages show.

but checkValid returns FALSE - so the form does not submit

@hueitan
Copy link
Owner

hueitan commented Jul 1, 2017

I'm not sure if I understand your description correctly, do you mind post your <Form> script here so that we can check your requirement.

@codeuniquely
Copy link
Author

codeuniquely commented Jul 1, 2017

I've worked out what the issue is ..

I have added an input like this

<input
    ng-class="{focus:form.optionalNumber.$focus===true}"
    ng-attr-type="text"
    id="optionalNumber"
    name="optionalNumber"
    autocomplete="off"
    pattern="\d*"
    ng-model="model.optionalNumber"
    maxlength="11"
    ng-focus="form.optionalNumber.$focus=true"
    ng-blur="form.optionalNumber.$focus=false"
    initial-validity=true
    validator="optionalNumber"
    invalid-callback="invalidMsg(message)" />

The validator looks like this

optionalNumber: function(value) {
   if(!value || value.length===0) {
     return true;
   }
   var regexp = expr.formattedNumber;
   return regexp.test(value);
},

The button submit calls this function

submit(form, state) {
  let isValid = this.$validationProvider.checkValid(form);
  if (isValid) {
    return this.save(state);
  }
  console.log('Invalid Form');
  this.$scope.form.submitted = true;
  this.scrollToFirstError();
}

The issue is that because that the input is optional - so the user never has to enter a value and can skip the form (so it never moves from $pristine and the $watch never fires because the user does not alter the value. This means that the $valid and $invalid values on the form never fire but the form input is added to the $pending array (for validation) - this means that the $invalid and $valid properties on the form are "undefined"

So to combat this added the initial-validation=true - so that the initial state would be set and if the user did nothing then the input would still be valid. However this does not work.

on line 687 of angular-validation.js you have this code

/**
 * Set initial validity to undefined if no boolean value is transmitted
*/
var initialValidity = void 0;
if (typeof attrs.initialValidity === 'boolean' ) {
    initialValidity = attrs.initialValidity;
} 

The issue here is that typeof attrs.initialValidity ALWAYS === 'string' because you are reading it from attrs so it will never be a boolean, it doesn't matter if you pass

initial-validity=true
initial-validity="true"
initial-validity="{{someConst}}" .   // where the const is true
initial-validity="{{someBinding}}"   // where the binding is to a variable that is true

When you inspect attrs..initialValidity its still a string, so the initial set up of the state is never set and so the optional model property validation remains "undefined" and the check fails.

there is a possible fix

Suggestion:

If you instead add a check for 'true' and 'false' when init initialValidity in your code...

if (typeof attrs.initialValidity === 'boolean' || attrs.initialValidity === 'true' || attrs.initialValidity === 'false') {
    initialValidity = attrs.initialValidity;
}

THEN it will work as expected ....

@codeuniquely codeuniquely changed the title CheckValid NOt Working CheckValid not working as expected Jul 4, 2017
@ghost
Copy link

ghost commented Mar 19, 2019

A possible solution I use without forking the project for now is a custom directive that does the initialization of the ngModel field validity.

export const ngModelInitialValidityDirective = ($parse) => {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: (scope, element, attrs, ngModelCtrl) => {
      const initialValidity = $parse(attrs[directiveName])(scope);

      if (_isBoolean(initialValidity)) {
        ngModelCtrl.$setValidity(ngModelCtrl.$name, initialValidity);
      }
    },
  };
};

ngModelInitialValidityDirective.$inject = ['$parse'];

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants