AngularJS <input> validation with no enclosing <form> - angularjs

Is it possible in Angular to validate a single, isolated <input> in a similar way the forms are validated? I'm thinking about something like this:
<div class="form-group">
<input name="myInput" type="text" class="form-control" ng-model="bindTo" ng-maxlength="5">
<span class="error" ng-show="myInput.$error.maxlength">Too long!</span>
</div>
The example above doesn't work. Enclosing it in a <form> and replacing ng-show with ng-show="myForm.myInput.$error.maxlength" helps.
Is it possible to do this without using <form>?

You may use the ng-form angular directive (see docs here) to group anything, even outside a html form. Then, you can take advantage from angular FormController.
<div class="form-group" ng-form name="myForm">
<input name="myInput" type="text" class="form-control" ng-model="bindTo" ng-maxlength="5">
<span class="error" ng-show="myForm.myInput.$error.maxlength">Too long!</span>
</div>
Example

Building on Silvio Lucas' answer, if you are iterating in a loop and need to be able to interpolate form names and valid states:
<div
name="{{propertyName}}"
ng-form=""
class="property-edit-view"
ng-class="{
'has-error': {{propertyName}}.editBox.$invalid,
'has-success':
{{propertyName}}.editBox.$valid &&
{{propertyName}}.editBox.$dirty &&
propertyValue.length !== 0
}"
ng-switch="schema.type">
<input
name="editBox"
ng-switch-when="int"
type="number"
ng-model="propertyValue"
ng-pattern="/^[0-9]+$/"
class="form-control">
<input
name="editBox"
ng-switch-default=""
type="text"
ng-model="propertyValue"
class="form-control">
<span class="property-type" ng-bind="schema.type"></span>
</div>

<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"> </script>
</head>
<body ng-controller="MainCtrl">
<div class="help-block error" ng-show="test.field.$error.required">Required</div>
<div class="help-block error" ng-show="test.firstName.$error.required">Name Required</div>
<p>Hello {{name}}!</p>
<div ng-form="test" id="test">
<input type="text" name="firstName" ng-model="firstName" required> First name <br/>
<input id="field" name="field" required ng-model="field2" type="text"/>
</div>
</body>
<script>
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.field = "name";
$scope.firstName = "FirstName";
$scope.execute = function() {
alert('Executed!');
}
});
</script>

Related

Angularjs 1 form validation issue

I am using Angularjs 1 in my project.i am validating the form inside angular,so i am using form.$valid to check the form submitted is valid or not,but it is not working properly,not sure what i am missing
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="utf-8" />
<title> Learning AngularJS Filters </title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
<script>
"use strict";
angular.module("myApp",[]);
angular.module("myApp").controller("SampleController",[function(){
this.user = {}
this.submitForm = function(form){
if(form.$valid){
window.alert("Valid")
}else{
window.alert("In Valid");
}
}
}]);
</script>
</head>
<body>
<div ng-controller="SampleController as sm" class="container">
<form name="sampleForm" novalidate>
<div class="form-group">
<label for="exampleInputEmail1"> Username </label>
<input type="text" class="form-control" ng-model="sm.user.name" id="exampleInputEmail1" placeholder="Enter Username" required>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" ng-model="sm.user.pwd" id="exampleInputPassword1" placeholder="Password" required>
</div>
<button type="submit" ng-click="sm.submitForm('sampleForm')" class="btn btn-primary">Submit</button>
<p> {{ sm.user }} </p>
</form>
</div> <!--/ container -->
</body>
</html>
I am always getting the alert message from the else part which states form invalid
Form directive is bounded to scope, so you need to write it as $scope.sampleForm.$valid. Since your name is dynamic, you can use a bracket notation: $scope[form].$valid. But either way you need to inject $scope into your controller.
Here is a demo:
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="utf-8" />
<title> Learning AngularJS Filters </title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
<script>
"use strict";
angular.module("myApp", []);
angular.module("myApp").controller("SampleController", ['$scope', function($scope) {
this.user = {}
this.submitForm = function(form) {
if ($scope[form].$valid) {
window.alert("Valid")
} else {
window.alert("In Valid");
}
}
}]);
</script>
</head>
<body>
<div ng-controller="SampleController as sm" class="container">
<form name="sampleForm" novalidate>
<div class="form-group">
<label for="exampleInputEmail1"> Username </label>
<input type="text" class="form-control" ng-model="sm.user.name" id="exampleInputEmail1" placeholder="Enter Username" required>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" ng-model="sm.user.pwd" id="exampleInputPassword1" placeholder="Password" required>
</div>
<button type="submit" ng-click="sm.submitForm('sampleForm')" class="btn btn-primary">Submit</button>
<p> {{ sm.user }} </p>
</form>
</div>
<!--/ container -->
</body>
</html>
You are passing form as a string in ng-click method not a form Object.So u have to pass the form object without Single-cotts.
ng-click="sm.submitForm('sampleForm')" to ng-click="sm.submitForm(sampleForm)"

AngularJS - ng-change only firing once when the page loads

I am writing an app with Angular 1.5. I have a form with a time input.
<div class="item item-input" ng-class="{ 'has-error' : accvm.addForm.time.$invalid }">
<span class="input-label" ng-i18next="TIME"></span>
<input name="time" type="time" max="{{ accvm.data.maxTime | date:'HH:mm' }}" ng-model="accvm.data.time" ng-change="accvm.timeChange()" style="text-align: right" required />
</div>
<div ng-messages="accvm.addForm.time.$error">
<div class="form-error" ng-message="required"><span ng-i18next="VALIDATION_PROJECT"></span></div>
<div class="form-error" ng-message="max"><span ng-i18next="VALIDATION_TIME_FUTURE"></span></div>
</div>
For some reason, the ng-change function is only called once when the page loads and never again even if I type a new value in. I am not sure what I am doing wrong.
Here is my JSFiddle: http://jsfiddle.net/aubz88/j25jwtL2/
ng-change is not firing method due to invalidation. Check this working code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Example - example-date-input-directive-production</title>
<script data-require="angular.js#1.3.15" data-semver="1.3.15" src="https://code.angularjs.org/1.3.15/angular.js"></script>
</head>
<body ng-app="dateInputExample">
<script>
angular.module('dateInputExample', [])
.controller('DateController', ['$scope', function($scope) {
$scope.changed = 0;
$scope.example = {
value: new Date(1999, 0, 1, 15, 30, 0)
};
$scope.change = function(){
$scope.changed ++;
}
}])
</script>
<form name="myForm" ng-controller="DateController as dateCtrl">
<label for="exampleInput">Picktime:</label>
<input type="time" time id="exampleInput" name="input" ng-model="example.value" placeholder="yyyy-MM-dd" required="" ng-change="change();" />
<div role="alert">
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.time">
Not a valid date!</span>
</div>
<tt>value = {{example.value | date: "HH:mm"}}</tt>
<br />
<div>The time has been changed
<ng-pluralize count="changed" when="{'0': '{} times.',
'one': '1 time.',
'other': '{} times.'}"></ng-pluralize>
</div>
</form>
<!--<form name="myForm" ng-controller="DateController as accvm">-->
<!-- <div class="item item-input" ng-class="{ 'has-error' : accvm.addForm.time.$invalid }">-->
<!-- <span class="input-label" ng-i18next="TIME"></span>-->
<!-- <input name="time" type="time" ng-model="accvm.data.time" ng-change="accvm.timeChange()" style="text-align: right" required />-->
<!-- </div>-->
<!-- <div ng-messages="accvm.addForm.time.$error">-->
<!-- <div class="form-error" ng-message="required"><span ng-i18next="VALIDATION_PROJECT"></span></div>-->
<!-- <div class="form-error" ng-message="max"><span ng-i18next="VALIDATION_TIME_FUTURE"></span></div>-->
<!-- </div>-->
<!-- {{changed}} {{accvm.addForm.time.$invalid}}-->
<!--</form>-->
I think the problem is with the different abbreviation that you are using in your controller and in your template, changing accvm for vm it's working fine for me.
Here's your JSFiddle updated: http://jsfiddle.net/j25jwtL2/58/

ng-if does not work

In my project I am facing an issue that ng-if is not working. I want to remove/add text field when value of $scope.edit changes.
I have created a simplest of example in the jsfiddle below.
HTML
<div ng-app>
<div ng-controller="TodoCtrl">
<input type="checkbox" ng-model="edit" ng-init="edit = true">
<div ng-bind="edit"></div>
<div ng-if="edit">
<input type="text" ng-model="name" size="30" placeholder="New Name" />
</div>
</div>
</div>
JS
function TodoCtrl($scope) {
$scope.name = "Johny";
}
http://jsfiddle.net/U3pVM/32009/
Your Fiddle may not work because you are using Angular 1.0.1 which has some issue in ng-if.
Solution 1
If you are really using this version, you can replace ng-if by ng-show (which will create hidden elements in the DOM).
<div ng-show="edit">
Demo on JSFiddle using ng-show
Solution 2
Anyway, the best solution would be to use Angular 1.2+ which fixes ng-if bugs in ng-repeat. As you can see in the following snippet, I didn't change your code, and it works.
Demo on JSFiddle using ng-if
Some observations :
Seems that your angular version is old. hence, ng-if is not working.
If you want to use only existing angular version then you can use ng-show instead of ng-if.
Demo with ng-if :
function TodoCtrl($scope) {
$scope.name = "Johny";
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<div ng-controller="TodoCtrl">
<input type="checkbox" ng-model="edit" ng-init="edit = true">
<div ng-bind="edit"></div>
<div ng-if="edit">
<input type="text" ng-model="name" size="30" placeholder="New Name" />
</div>
</div>
</div>
Demo with ng-show :
function TodoCtrl($scope) {
$scope.name = "Johny";
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular.min.js"></script>
<div ng-app>
<div ng-controller="TodoCtrl">
<input type="checkbox" ng-model="edit" ng-init="edit = true">
<div ng-bind="edit"></div>
<div ng-show="edit">
<input type="text" ng-model="name" size="30" placeholder="New Name" />
</div>
</div>
</div>
Use ng-show instead
<div ng-show=edit>
<input type="text" ng-model="name" size="30" placeholder="New Name" />
</div>
DEMO
Update the angular version with 1.2 or above with ng-if
angular.module('myApp', [])
.controller('TestCtrl', function($scope) {
$scope.name = "Johny";
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>AngularJS </title>
<link rel="stylesheet" href="style.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.5/angular.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="TestCtrl">
<input type="checkbox" ng-model="edit" ng-init="edit = true">
<div ng-bind="edit"></div>
<div ng-show=edit>
<input type="text" ng-model="name" size="30" placeholder="New Name" />
</div>
</body>
</html>

AngularJS scope form is underfined while multiple forms on page

Firstly if have only one form on page, like:
<form class="form-horizontal" name="formCreateCtb">
...
Then i can easily access it in my controller in following way:
$scope.formCreateCtb.$setPristine(); // reset form validation
But as soon as i added second form on page, like:
<form class="form-horizontal" name="formCreateCtb">
...
<form class="form-horizontal" name="formCreateCtbs">
...
Then i can't access second form in scope like previosly:
$scope.formCreateCtb.$setPristine(); // still work OK
$scope.formCreateCtbs.$setPristine(); // Exception: formCreateCtbs is underfined
Why this behavior, and how to access form in scope, when i have multiple forms on page.
Thanks!
EDIT:
It seems the issue is that in project i have more complex markup, the second form
live in bootstrap tab, that is not visible at the moment of forms shown.
When i added second form out of modal, it works fine. The workaround is wrap entire tabs in one form element.
Use the ng-form directive
Online Demo - http://codepen.io/anon/pen/AXxVvY?editors=1010#0
html
<form name="formCreateCtb" novalidate>
<ng-form name="formCreateCtb">
<label>Email</label>
<input type="text" class="form-control" name="email" ng-model="email" required>
<p class="help-block" ng-show="formCreateCtb.email.$invalid">Valid Email Address Required</p>
</ng-form>
</form>
<form name="formCreateCtbs" novalidate>
<ng-form name="formCreateCtbs">
<label>Email 2</label>
<input type="text" class="form-control" name="email2" ng-model="email2" required>
<p class="help-block" ng-show="formCreateCtbs.email2.$invalid">Valid Email Address Required</p>
</ng-form>
</form>
<button ng-click="setPristine()">call setPristine</button>
js
.controller('mainController', function($scope) {
$scope.setPristine = function() {
$scope.formCreateCtb.$setPristine();
$scope.formCreateCtbs.$setPristine();
console.log('setPristine');
};
});
It is working for me.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $compile) {
'use strict';
$scope.data = {
"name": ""
};
$scope.reset = function() {
$scope.data.name = "";
$scope.form.$setPristine();
}
$scope.reset1 = function() {
$scope.data.name1 = "";
$scope.form1.$setPristine();
}
});
input.ng-invalid.ng-dirty {
background-color: #FA787E;
}
input.ng-valid.ng-dirty {
background-color: #78FA89;
}
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8">
<title>AngularJS Plunker</title>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css">
<script src="http://code.jquery.com/jquery-1.10.0.min.js"></script>
<script data-require="angular.js#1.0.x" src="http://code.angularjs.org/1.1.5/angular.min.js" data-semver="1.0.7"></script>
<script src="app.js"></script>
</head>
<body>
<div ng-controller="MainCtrl">
<form name="form" id="form" novalidate>
<input name="name" ng-model="data.name" placeholder="Name" required/>
<button class="button" ng-click="reset()">Reset</button>
</form>
<form name="form1" id="form1" novalidate>
<input name="name1" ng-model="data.name1" placeholder="Name1" required/>
<button class="button" ng-click="reset1()">Reset</button>
</form>
<p>Pristine: {{form.$pristine}}</p>
<p> <pre>Errors: {{form.$error | json}}</pre>
<p>Pristine: {{form1.$pristine}}</p>
<p> <pre>Errors: {{form1.$error | json}}</pre>
</div>
</body>
</html>
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $compile) {
'use strict';
$scope.data = {
"name": ""
};
$scope.reset = function() {
$scope.data.name = "";
$scope.form.$setPristine();
}
$scope.reset1 = function() {
$scope.data.name1 = "";
$scope.form1.$setPristine();
}
});
input.ng-invalid.ng-dirty {
background-color: #FA787E;
}
input.ng-valid.ng-dirty {
background-color: #78FA89;
}
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8">
<title>AngularJS Plunker</title>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css">
<script src="http://code.jquery.com/jquery-1.10.0.min.js"></script>
<script data-require="angular.js#1.0.x" src="http://code.angularjs.org/1.1.5/angular.min.js" data-semver="1.0.7"></script>
<script src="app.js"></script>
</head>
<body>
<div ng-controller="MainCtrl">
<form name="form" id="form" novalidate>
<input name="name" ng-model="data.name" placeholder="Name" required/>
<button class="button" ng-click="reset()">Reset</button>
</form>
<form name="form1" id="form1" novalidate>
<input name="name1" ng-model="data.name1" placeholder="Name1" required/>
<button class="button" ng-click="reset1()">Reset</button>
</form>
<p>Pristine: {{form.$pristine}}</p>
<p> <pre>Errors: {{form.$error | json}}</pre>
<p>Pristine: {{form1.$pristine}}</p>
<p> <pre>Errors: {{form1.$error | json}}</pre>
</div>
</body>
</html>

angular js form showing validation alerts all the time

I am really new to angular and I am just browsing its capabilities which are incredibly impressive so far...I created this simple username field validation:
<!Doctype html>
<html>
<head>
<title>form validation</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
</head>
<body>
<form name="form">
Name:
<input type="text"
name="uName"
placeholder="username"
ng-minlength=3
ng-maxlength=20
ensure-unique="username" required /><br />
<div ng-show="form.uName.$dirty && form.uName.$invalid">
<small ng-show="form.uName.$error.required">please put your username in</small>
<small ng-show="form.uName.$error.minlength">it has to be at least 3 characters</small>
<small ng-show="form.uName.$error.maxlength">it can't be longer than 20 characters</small>>
<small ng-show="form.uName.$error.unique">this one has already been taken</small>
</div>
</form>
</body>
</html>
however it just shows all of the validation errors...I am now sure why, I am also missing a model, but I again I don't know if it is necessary.
http://jsbin.com/hekaz/1/edit
<form name="form">
Name:
<input type="text"
name="uName"
placeholder="username"
ng-minlength=3
ng-maxlength=20
ensure-unique="username" required ng-model="username"/><br />
<div ng-show="form.uName.$dirty && form.uName.$invalid">
<small ng-show="form.uName.$error.required">please put your username in</small>
<small ng-show="form.uName.$error.minlength">it has to be at least 3 characters </small>
<small ng-show="form.uName.$error.maxlength">it can't be longer than 20 characters</small>
<small ng-show="form.uName.$error.unique">this one has already been taken</small>
</div>
</form>
I noticed three things.
1.You miss ng-app on the html tag:
<html ng-app="myApp">
2.You miss a controller, ie:
<script>
var myApp = angular.module('myApp', []);
function ControllerCtrl ($scope) {
$scope.username='';
};
</script>
3.You miss ng-model in your input:
ng-model="username"
Full working code:
<!Doctype html>
<html ng-app="myApp">
<head>
<title>form validation</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
<script>
var myApp = angular.module('myApp', []);
function ControllerCtrl ($scope) {
$scope.username='';
};
</script>
</head>
<body>
<form name="form">
Name:
<input type="text"
name="uName"
placeholder="username"
ng-minlength=3
ng-maxlength=20
ensure-unique="username" required ng-model="username"/><br />
<div ng-show="form.uName.$dirty && form.uName.$invalid">
<small ng-show="form.uName.$error.required">please put your username in</small>
<small ng-show="form.uName.$error.minlength">it has to be at least 3 characters</small>
<small ng-show="form.uName.$error.maxlength">it can't be longer than 20 characters</small>>
<small ng-show="form.uName.$error.unique">this one has already been taken</small>
</div>
</form>
</body>
</html>

Resources