Rectangle 27 137

When you put <form> tag inside you ngApp, AngularJS automatically adds form controller (actually there is a directive, called form that add nessesary behaviour). The value of the name attribute will be bound in your scope; so something like <form name="yourformname">...</form> will satisfy:

A form is an instance of FormController. The form instance can optionally be published into the scope using the name attribute.

So to check form validity, you can check value of $scope.yourformname.$valid property of scope.

Normally it would be called inside the JS as $scope.yourformname.$valid.

always got error Cannot read property '$valid' of undefined

You need to explicitly give the form some name like <form name="form">, then $scope.form should be available..

if the property doesn't seems to be defined in controller, explicitly initialize it in controller $scope.myformname = {};

@JohnNguyen i got the same exact error. there's this workaround i did. In your submit function, pass the form as an argument. you can then go to your controller and check to see if the form is valid by yourFormName.$valid. They used this example in the Angular documentation, their plunker found here: plnkr.co/edit/Q8mlPOSgkaPstg4uvjlc?p=preview

How do I check form validity with angularjs? - Stack Overflow

angularjs
Rectangle 27 9

I think a better solution is to just add your own CSS rules. It makes the code much simpler and, as a bonus, you can set the rule to only apply to "dirty" elements. That way fields will only be highlighted after the user has tried to enter something.

In my application I've just added this css, based on an example in the AngularJS forms documentation.

/* Forms */
.ng-invalid.ng-dirty {
  border-color: red;
  outline-color: red;
}
.ng-valid.ng-dirty {
  border-color: green;
  outline-color: green;
}

javascript - How to set Twitter Bootstrap class=error based on Angular...

javascript html css twitter-bootstrap angularjs
Rectangle 27 3

Take a look at the angularjs form documentation - http://docs.angularjs.org/guide/forms . In general, it is based on the HTML5 attributes like required, min, max, etc.

To get, for example, your first requirement done - "an empty field should show "Field must contain a value" message, yo uwould do something like that:

<input type="text" ng-model="user.name" name="uName" required /><br />
<div ng-show="form.uName.$invalid">
  <span ng-show="form.uName.$error.required">Field must contain a value.</span>
</div>
pattern

For even number validation, I'm not sure - I think you'd have to go with custom validation for that (meaning you'd have to create a directive) or use the pattern attribute somehow.

Last but not least - remember to add novalidate to the <form> tag. Otherwise the browser will try to validate your fields as well and you don't want that:

<form ... novalidate>
 ...
</form>

You answered my q only regarding "require" attribute. As for the rest, maybe I did not make my Q clear enough, I want to use JavaScript function that would make the correct validation on each user key press to the field (or leaving the field)

I wrote what should be done for the digits and even number validation - for digits you can use the pattern attribute (no need for custom JS function). For the even number validation, that's trickier and I don't think you will be able to get away without a directive.

So why are you using angularjs if you don't wanna use its capabilities?

Angularjs Form/Field validation using JavaScript function without dire...

javascript validation angularjs angular-ui ui-validate
Rectangle 27 1

Everything you need to do this is available in Angular, but it's not immediately obvious how. First, according to the AngularJS Forms Guide, you should surround your <input /> elements with a form with a name attribute. For example:

<form name="myForm">
  <input type="text" ng-model="formData.userName" name="userName" />
</form>

Now, within your controller's $scope, you can access an FormController instance using $scope.myForm, which has many useful properties. For example, the $valid property.

You could use this in your controller as simply as:

if ($scope.myForm.$valid) {
  // do something with the comfort that all your fields are validated
}

You can also access individual input's validation status (assuming you supplied a name attribute for those too), using something $scope.myForm.userName.$valid.

The great part is this is running after each model update, so there is no need to dispatch a custom event. Angular will run the validation code and set the variables for you, which erases your problem with trying get asynchronous code to behave synchronously.

If you don't need any special validation on your inputs other than what Angular provides (email, number, url, etc.), simply add the appropriate attributes and Angular will do the right thing, making the results available on the FormController's $valid and $error properties.

There is a pretty simple way to make custom validators (see the integer example for a trivial example). I haven't actually written a more complex validator than that, so I'll leave explaining more of that to the Angular documentation and other Stackoverflow answers.

javascript - AngularJS : validate before continuing - Stack Overflow

javascript angularjs
Rectangle 27 1

from the angularjs docs for forms:

A form is an instance of FormController. The form instance can optionally be published into the scope using the name attribute.

Similarly, an input control that has the ngModel directive holds an instance of NgModelController. Such a control instance can be published as a property of the form instance using the name attribute on the input control. The name attribute specifies the name of the property on the form instance.

This implies that the internal state of both the form and the control is available for binding in the view using the standard binding primitives.

What this means is that if you add the name attribute to your form then you get access to the form and all it's properties in your scope, this means that you're given access to all the information you need for validating your form including if it's valid or not, pristine or dirty etc. In order for this to work you need 2 main things:

  • Add name attribute to your form, this will be the name of the variable to get the form data. So name = "myform" stores the form in $scope.myform.
  • Add ng-model to all your inputs, if an input doesn't have an ng-model then it won't be considered in the form's validation.

After that you can always find out if your form is valid using $scope.myform.$valid. As an added bonus you could also add the name property to each input, this will also add an object for each input inside the $scope.myform containing all the information for that input and it's validation.

javascript - ng-disabled not working when input fields are in an ng-re...

javascript angularjs angular-meteor
Rectangle 27 15

Mixing in parameters on the form

Angular comes out of the box with an improve tag that is documented here. Basically it creates a scope in the form of a controller around the form and all of the tags within it. So you do this:

var app = angular.app('TestApp', []);
app.controller('FormCtrl', function($scope) {
    $scope.submit = function() {
        // Form submit logic here
        console.log("Submitting the form");
        console.log($scope);
    }
})

This creates a scope for the form, since the form tag contains the ng-controller tag. Within the scope, testForm is the javascript object for the form, and testForm.firstInput is the javascript object for the first input. It looks like these objects also have some validation functionality available, see docs here.

The data on the form will be available as an object data in the FormCtrl scope, with keys "first" and "second", and you can define methods in the controller that work on that.

You can also put multiple forms using the same FormCtrl, and it seems like Angular will create new instances for each form, so you don't have to worry about forms polluting each other's data.

Now lets suppose that we have some sort of complex input or widget that is implemented in a directive. This example uses two select boxes to display all cities in a state. You have to first select a state, then it'll query for the cities in that state and populate the second select box.

app.directive('citySelect', function() {
    return {
        replace: true,
        template: '<div><select ng-change="getCities()" ng-options="s.name for s in states"></select>' +
                  '<select ng-model="data.selectedCity" ng-options="c.name for c in cities"></select>',
        controller: function($scope) {
            // Omitting the logic for getCities(), but it'd go here
        }
    };
})

Then you can just stick it into the form tag, and it'll work. Because the directive doesn't define a scope, it'll just attach to the scope of the FormCtrl.

EDIT: So apparently this does work:

You simply do it without the curlies, and it'll bind. My guess is that the parent scope is binding to someParameter in the child scope, and the select is then binding to somParameter in the child scope.

So all of this below about manually compiling in the link function is not necessary.

But the problem with this is that my citySelect directive has a hard coded ng-model binding, so if I created some sort of generic widget, I couldn't use more than one of it in a form. Unfortunately this does not seem to work:

scope: {someParameter: "="},
template: '<div><select ng-model="{{ someParameter }}"></select></div>'

The only way that I have gotten this to work is to build the DOM element manually in a linking function, but I'm not sure if this is advisable. I would appreciate comments from anyone about this implementation:

<body ng-app="TestApp">
<form ng-controller="FormCtrl" name="testForm">
    <input name="firstInput" ng-model="data.first">
    <input name="secondInput" ng-model="data.second">
    <div city-select bind-to="data.homeCity"></div>
    <div city-select bind-to="data.workCity"></div>
    <button ng-click="submit()">Submit</button>
</form>
</body>

app.directive('citySelect', function($compile) {
    return {
        replace: true,
        template: '<div></div>',
        controller: function($scope) {
            // Omitting the logic for getCities(), but it'd go here
        }
        link: function(scope, iElem, iAttrs) {
            var html = '<div><select ng-bind="' + iAttrs['bindTo'] + '"></div>';
            iElem.replaceWith($compile(html)(scope));
        }
    };
})

Since separate instances of FormCtrl are created for each form, you can reuse a lot of the functionality in FormCtrl. But you can also use additional directives on a form tag to add parameters or break apart functionality. For example:

<form ng-controller="FormCtrl" name="testForm" post-form post-path="/path/to/resource/">

app.directive('postForm', function() {
    return {
        controller: function($scope) {
            $scope.post = function() {
                // Some generic POST behavior
            };
        },
        link: function(scope, iElem, iAttr) {
            scope.postPath = iAttr['postPath'];
        },
    };
});

The form's scope will then combine the scope from FormCtrl and postForm, so that everything is accessible. In my experimentation, it seems like the FormCtrl takes precedence, so if something like $scope.submit() is defined in both FormCtrl and postForm, FormCtrl's will take precedence (I think), maybe this is a race condition from asynchronous loading, I don't know.

Instead of using ng-controller, I think you can also use scope:true on the mixin directive (postForm), or perhaps more safely, scope: {}.

AngularJS - Modular forms with directives - Stack Overflow

forms angularjs angularjs-directive
Rectangle 27 1

inputCtrl.inputForm.$setPristine();
$scope.inputForm.$setPristine();
this
$scope

angularjs - TypeError: Cannot read property '$setPristine' of undefine...

angularjs
Rectangle 27 1

inputCtrl.inputForm.$setPristine();
$scope.inputForm.$setPristine();
this
$scope

angularjs - TypeError: Cannot read property '$setPristine' of undefine...

angularjs
Rectangle 27 36

Here is my solution inspired by mbernath, that isolates completely the form itself from its father.

This solution take care of the:

See it in action in this JSFiddle.

angular.module('isolateForm',[]).directive('isolateForm', [function () {
    return {
        restrict: 'A',
        require: '?form',
        link: function (scope, elm, attrs, ctrl) {
            if (!ctrl) {
                return;
            }

            // Do a copy of the controller
            var ctrlCopy = {};
            angular.copy(ctrl, ctrlCopy);

            // Get the parent of the form
            var parent = elm.parent().controller('form');
            // Remove parent link to the controller
            parent.$removeControl(ctrl);

            // Replace form controller with a "isolated form"
            var isolatedFormCtrl = {
                $setValidity: function (validationToken, isValid, control) {
                    ctrlCopy.$setValidity(validationToken, isValid, control);
                    parent.$setValidity(validationToken, true, ctrl);
                },
                $setDirty: function () {
                    elm.removeClass('ng-pristine').addClass('ng-dirty');
                    ctrl.$dirty = true;
                    ctrl.$pristine = false;
                },
            };
            angular.extend(ctrl, isolatedFormCtrl);
        }
    };
}]);

To use it just call the directive "isolate-form" :

<form name="parent">
    <input type="text" ng-model="outside"/>
    <ng-form name="subform" isolate-form>
        <input type="text" ng-model="inside"/>
    </ng-form>
</form>

worked like a charm! thanks for the very explanatory example thought.

You're welcome! I had to find a solution at work and present the solution. So I imagined this ;)

Does this no longer work? Because right now in the fiddle, all child forms need to be valid before the parent form is valid, and that's the opposite of what the original question asks.

This no longer works as of Angular 1.6 due to limitations on copying objects containing scopes. angular.copy will produce an error (docs.angularjs.org/error/ng/cpws)

javascript - Skip nested forms validation with AngularJS - Stack Overf...

javascript angularjs
Rectangle 27 9

I found a better way without JQuery. I found this answer long back, but now I remembered to update here after a year. The forms will be available in $scope object. So just give a name to the form and use it.

<form id="userRegistration" name="registration" ng-submit="registerUser()" >
$scope.registerUser=function()
    {
       if ($scope.registration.$valid){
           alert("Submitting...");
       }
    }
angular.module('myApp').controller('RegisterController', function($scope,$http) {
    page.setPage("Register","login-layout");
    $scope.user = {};
    $scope.registerUser=function()
    {
       if ($("#userRegistration").valid()){
           alert("Submitting...");
       }
    }
});

javascript - AngularJS form submit not working with JQuery validation ...

javascript jquery forms validation angularjs
Rectangle 27 1

Use the required attribute on inputs to prevent form submission of empty fields:

<form  action="/listings"  name="listings" ng-submit="searchListings()">
    <input type="text" name="neighborhood" placeholder="Neighborhood:"
           ng-model="fdata.state"  required />    
    <input type="text" name="town" placeholder="Town:" 
           ng-model="fdata.city" required />
    <input type="text" name="country" placeholder="Country:"
           ng-model="fdata.country"  required />            
    People:<select class="peopleSelect" placeholder="People:"
                   ng-model="fdata.accommodates"  required /> 
           </select> 
    <input type="text" id="arrival" name="arrival" value="Arrival"
           ng-model="fdata.checkIn"  required />
    <input type="text" id="departure" name="depart" value="Departure"
           ng-model="fdata.checkOut"  required />
    <input type="submit" name="submit" value="Search" id="Search_submit" />
</form>

Also notice how the ng-model attributes have been changed to put the data on a JavaScript object. This makes it easier to submit:

$scope.fdata = {};
var url = "http://www.localhost:8080/messenger/webapi/listings";

$scope.searchListings = function() {
    var config = { params: fdata };

    $http.get(url, config)
      .then(function(response) {
        $scope.message = response.data;
    })
      .catch(function(response) {
        var data = response.data;
        console.log( "failure message: " + JSON.stringify({data: data}));
        throw response;
    });             

};

Also be aware that the $http .success and .catch methods have been deprecated and removes from AngularJS v1.6. Instead, use the .then and .catch methods.

You did not understand my question here. Not all input input fields are required and what i want is to check if they are empty. If one field is empty i dont want it to be as a search parameter. Think of them as filters, i want to check which of them are enabled

@GeorgeSp, StackOverflow is not a code writing service. You need to show code for what you have tried to achieve what you want. If you want to create a params object which omits properties for empty fields, that is a trivial problem.

jersey - How to check if query params are empty with AngularJS forms -...

angularjs jersey angularjs-forms
Rectangle 27 28

trainosais - you are right, validation should be done on a directive level. It's clean, modular and allows for reusability of code. When you have basic validation like that in a controller you have write it over and over again for different forms. That's super anti-dry.

I had a similar problem recently and sorted it out with a simple directive, which plugs in to the parsers pipeline, therefore stays consistent with Angular architecture. Chaining validators makes it very easy to reuse and that should be considered the only solution in my view.

Without further ado, here's the simplified markup:

<form novalidate="novalidate">
    <label>email</label>
    <input type="text"
        ng-model="email"
        name="email" />
    <label>email repeated</label>
    <input ng-model="emailRepeated"
        same-as="email"
        name="emailRepeated" />
</form>
angular.module('app', [])
    .directive('sameAs', function() {
        return {
            require: 'ngModel',
            link: function(scope, elem, attrs, ngModel) {
                ngModel.$parsers.unshift(validate);

                // Force-trigger the parsing pipeline.
                scope.$watch(attrs.sameAs, function() {
                    ngModel.$setViewValue(ngModel.$viewValue);
                });

                function validate(value) {
                    var isValid = scope.$eval(attrs.sameAs) == value;

                    ngModel.$setValidity('same-as', isValid);

                    return isValid ? value : undefined;
                }
            }
        };
    });

The directive hooks into the parsers pipeline in order to get notified of any changes to the view value and set validity based on comparison of the new view value and the value of the reference field. That bit is easy. The tricky bit is sniffing for changes on the reference field. For that the directive sets a watcher on the reference value and force-triggeres the parsing pipeline, in order to get all the validators run again.

ngModel.$setViewValue(ngModel.$viewValue);
$parsers
validate(ngModel.$viewValue);

Comparing two input values in a form validation with AngularJS - Stack...

forms angularjs validation
Rectangle 27 28

trainosais - you are right, validation should be done on a directive level. It's clean, modular and allows for reusability of code. When you have basic validation like that in a controller you have write it over and over again for different forms. That's super anti-dry.

I had a similar problem recently and sorted it out with a simple directive, which plugs in to the parsers pipeline, therefore stays consistent with Angular architecture. Chaining validators makes it very easy to reuse and that should be considered the only solution in my view.

Without further ado, here's the simplified markup:

<form novalidate="novalidate">
    <label>email</label>
    <input type="text"
        ng-model="email"
        name="email" />
    <label>email repeated</label>
    <input ng-model="emailRepeated"
        same-as="email"
        name="emailRepeated" />
</form>
angular.module('app', [])
    .directive('sameAs', function() {
        return {
            require: 'ngModel',
            link: function(scope, elem, attrs, ngModel) {
                ngModel.$parsers.unshift(validate);

                // Force-trigger the parsing pipeline.
                scope.$watch(attrs.sameAs, function() {
                    ngModel.$setViewValue(ngModel.$viewValue);
                });

                function validate(value) {
                    var isValid = scope.$eval(attrs.sameAs) == value;

                    ngModel.$setValidity('same-as', isValid);

                    return isValid ? value : undefined;
                }
            }
        };
    });

The directive hooks into the parsers pipeline in order to get notified of any changes to the view value and set validity based on comparison of the new view value and the value of the reference field. That bit is easy. The tricky bit is sniffing for changes on the reference field. For that the directive sets a watcher on the reference value and force-triggeres the parsing pipeline, in order to get all the validators run again.

ngModel.$setViewValue(ngModel.$viewValue);
$parsers
validate(ngModel.$viewValue);

Comparing two input values in a form validation with AngularJS - Stack...

forms angularjs validation
Rectangle 27 9

When a form invalidates, the FormController contains an $error property.

$error Is an object hash, containing references to controls or forms with failing validators.

So you can simply loop through the error object and use NgModelController's $setDirty() on each control:

// "If the name attribute is specified, the form controller is published onto the current scope under this name."
var form = scope.myForm;

if (form.$invalid) {
    angular.forEach(form.$error, function(controls, errorName) {
        angular.forEach(controls, function(control) {
            control.$setDirty();
        });
    });
}

I actually like this solution a lot. It's fairly concise and doesn't require defining custom directives, while still avoiding having to reference any controls by name in your controller. (BTW, you don't have to use angular.forEach for this to work - you can iterate over the controls however you want - but that's just a matter of preference.)

Using AngularJS, how do I set all form fields to $dirty at once? - Sta...

angularjs
Rectangle 27 20

Look at the source code of the 'modal' of angular ui bootstrap, you will see the directive has

transclude: true

This means the modal window will create a new child scope whose parent here is the controller $scope, as the sibling of the directive scope. Then the 'form' can only be access by the newly created child scope.

One solution is define a var in the controller scope like

$scope.forms = {};

Then for the form name, we use something like forms.formName1. This way we could still access it from our controller by just call $scope.forms.formName1.

This works because the inheritance mechanism in JS is prototype chain. When child scope tries to create the forms.formName1, it first tries to find the forms object in its own scope which definitely does not have it since it is created on the fly. Then it will try to find it from the parent(up to the prototype chain) and here since we have it defined in the controller scope, it uses this 'forms' object we created to define the variable formName1. As a result we could still use it in our controller to do our stuff like:

if($scope.forms.formName1.$valid){
      //if form is valid
}

More about transclusion, look at the below Misco's video from 45 min. (this is probably the most accurate explanation of what transcluded scopes are that I've ever found !!!)

Only this did the trick for me. Thanks!

AngularJs can't access form object in controller ($scope) - Stack Over...

angularjs
Rectangle 27 19

Take a look at the ng-form directive. It allows nesting forms (actually not HTML <form>s, but Angular NgFormControllers). So you can split your one form, used for posting to the server, into two logical forms, used for independent validation:

<form submit="save()">
    <div ng-form="form1">
        ...controls...
        <button ng-click="proceed()"
            ng-disabled="form1.$invalid">Proceed</button>
    </div>
    <div ng-form="form2">
        ...controls...
        <button type="submit"
            ng-disabled="form2.$invalid || form1.$invalid">Submit</button>
    </div>
</form>

validation - angularjs: trigger form validate programmatically (inside...

forms validation angularjs
Rectangle 27 6

so, user the form name, on "save" click for example just pass the formName as a parameter and hey presto form available in save method (where formScopeObject is greated based upon the ng-models specifications you set in your form OR if you are editing this would be the object storing the item being edited i.e. a user account)

<form name="formExample" novalidate>

<!-- some form stuff here -->
Name
<input type="text" name="aField" ng-model="aField" required="" />

<br /><br />

<input type="button" ng-click="Save(formExample,formScopeObject)" />

</form>

AngularJs can't access form object in controller ($scope) - Stack Over...

angularjs
Rectangle 27 82

You should try setting type="button" on the buttons.

twitter bootstrap - AngularJS: All buttons inside form triggers submit...

twitter-bootstrap angularjs
Rectangle 27 5

I expand the @caitp and @Thinkscape solution a bit, to allow dynamically created nested ng-forms, like this:

<div ng-controller="ctrl">
    <ng-form name="form">
        <input type="text" ng-model="static" name="static"/>

        <div ng-repeat="df in dynamicForms">
            <ng-form name="form{{df.id}}">
                <input type="text" ng-model="df.sub" name="sub"/>
                <div>Dirty: <span ng-bind="form{{df.id}}.$dirty"></span></div>
            </ng-form>
        </div>

        <div><button ng-click="consoleLog()">Console Log</button></div>
        <div>Dirty: <span ng-bind="form.$dirty"></span></div>
    </ng-form>      
</div>

Dynamic validation and name in a form with AngularJS - Stack Overflow

angularjs
Rectangle 27 5

I expand the @caitp and @Thinkscape solution a bit, to allow dynamically created nested ng-forms, like this:

<div ng-controller="ctrl">
    <ng-form name="form">
        <input type="text" ng-model="static" name="static"/>

        <div ng-repeat="df in dynamicForms">
            <ng-form name="form{{df.id}}">
                <input type="text" ng-model="df.sub" name="sub"/>
                <div>Dirty: <span ng-bind="form{{df.id}}.$dirty"></span></div>
            </ng-form>
        </div>

        <div><button ng-click="consoleLog()">Console Log</button></div>
        <div>Dirty: <span ng-bind="form.$dirty"></span></div>
    </ng-form>      
</div>

Dynamic validation and name in a form with AngularJS - Stack Overflow

angularjs