4

I have the following simple form with an type='email' input bound to a model:

<div ng-app>
    <h2>Clearing ng-model</h2>
    <div ng-controller="EmailCtrl">
        <form name="emailForm" ng-submit="addEmail()">
            <input type="email" name="email" ng-model="userEmail" placeholder="email@domain.com">
            <span ng-show="emailForm.email.$invalid && emailForm.email.$dirty">invalid email</span>
            <span ng-show="emailForm.$invalid">form invalid!</span>
        </form>
        <br/>
        <button ng-click="clearViaUndefined()">clear via undefined</button>
        <button ng-click="clearViaNull()">clear via null</button>
        <button ng-click="clearViaEmptyString()">clear via empty string</button>
    </div>
</div>

Suppose the user enters an invalid email but then clicks a 'Cancel' button...so the form needs to be reset.

In the ng-click handler for the 'Cancel' button, if I set the value of the model to 'undefined' this does not change the input element's $valid property back to true (nor the form's for that matter).

function EmailCtrl($scope) {

    $scope.clearViaUndefined = function () {
        $scope.userEmail = undefined;
    };

    $scope.clearViaNull = function () {
        $scope.userEmail = null;
    };

    $scope.clearViaEmptyString = function () {
        $scope.userEmail = "";
    };
}

If I set the value of the model to an empty string "" or to null, then the $valid property does get set back to true.

Why is this?

I have a JS Fiddle here demonstrating the behaviour:

http://jsfiddle.net/U3pVM/12830/

Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
JTech
  • 3,420
  • 7
  • 44
  • 51
  • I'm not seeing the problem -- All the buttons clear the input form for me ... (Chrome). – mgilson Feb 05 '15 at 06:51
  • It is only a problem if you enter an invalid email - because I am trying to reset the $valid status of the form from 'false' back to 'true' - so if you enter a valid email, then the $valid value is already 'true' - hope that makes sense. – JTech Feb 05 '15 at 23:20

2 Answers2

19

Whenever you use ng-model on an input or select tag, angular internally manages two values for the field, one is $viewValue and other is $modelValue

$viewValue -> Used for display purpose on view

$modelValue-> Actual value which is used inside scope.

When using an input tag with type='email' Angular constantly validates the input value.

And if the value does not validate as a correct email, angular internally will set $modelValue to undefined and will set the form.fieldName.$error.fieldName attribute to true. So that field becomes invalid.

If you check the value of form.fieldName.$modelValue inside the controller you will find it as undefined.

So setting the model to 'undefined' in the controller, when the field is already invalid, changes nothing.

But if you set it to null or "" it will work as $modelValue and $viewValue both get changed - making the field valid again.

Hope this has cleared your understanding. Thanks.

Community
  • 1
  • 1
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
  • 1
    how can i show error messages like "Required field" when field is blank or "Invalid email id" when field has invalid email? – rajeshpanwar Mar 02 '15 at 12:20
  • I am checking the validation in controller and showing the message from controller. For invalid email, i am always getting blank data, so it is showing "Required field" every time. Can i show different messages by using controller. – rajeshpanwar Mar 02 '15 at 14:14
  • thanks a lots. but i have a lots of form and rendering them using ng-repeat on form fields. i am using validation.js for every form validation. I am not using angularjs form validation. i am setting $scope.errors.[field.name] = "massage" by using validation.js. Can i achieve by using javascript validation. – rajeshpanwar Mar 02 '15 at 14:33
  • @rajeshpanwar Surely there should be a way to do it..for that i need to look at code..please Do create and Question with plunkr/jsfiddle.. here it is not good place to solve the issue.. :) – Pankaj Parkar Mar 02 '15 at 14:46
  • @rajeshpanwar take a look at this somewhat similar rendering form inside ng-repeat http://stackoverflow.com/questions/28118134/angular-directive-with-dynamically-generated-input-fields-not-able-to-display-va/28146946#28146946 – Pankaj Parkar Mar 02 '15 at 15:34
  • I have created an simple example of myform. Please look at it : http://plnkr.co/edit/EHf2REss3qNbDo9SCRCK?p=preview – rajeshpanwar Mar 03 '15 at 05:17
  • @rajeshpanwar I already told you that, do open one separate question, so i can help you out there.. – Pankaj Parkar Mar 03 '15 at 05:33
5

Add ng-model-options="{allowInvalid: true}" on input field

then try setting ng-model to undefined hopefully will make the form/input valid again

see: https://docs.angularjs.org/api/ng/directive/ngModelOptions

Noman Chali
  • 330
  • 3
  • 15