I have multiple input fields and I want to validate my fields. They can't b blank when user click on submit button. How I will show border red when user click on button if fields are empty.
here is my code
http://plnkr.co/edit/XtnSdO9ARpHdn9RZotMt?p=info
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.c = [
{
name:'abc'
},
{
name:'pqr'
}
];
$scope.onclick =function(){
console.log($scope.c)
}
});
First of all, you need to put all input fields inside form tag. Like this:
<form ng-submit="onclick()">
<button type="submit">submit</button>
<li ng-repeat="x in c">
<input type="text" ng-model='x.name' value="{{x.name=='abc'?'ddd':'hhh'}}" required="true"/>
</li>
</form>
For input's you need to set property required="true" (or angular's ng-required, if you need conditional values). Sumbit button need to have type="submit" (so he triggers form submission). Submit function needs to be moved from button on-click to form's property ng-submit="onclick()".
This example will already work with native html5 validation messages.
If you want to add custom styles, input's which are not valid will have css class ('ng-invalid') on them.
It is best to use required attribute on your fields. But you can do manual validation with a directive. You just need to wrap your inputs in a <form>. This directive can be extended to do any validation you want. Here is an example of one:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.name = 'World';
$scope.c = [{
name: 'abc'
}, {
name: 'pqr'
}];
$scope.onclick = function() {
console.log($scope.c)
}
});
app.directive("emptyValidator", function($q, $timeout) {
return {
restrict: "A",
require: 'ngModel',
link: function(scope, element, attrs, ctrl) {
ctrl.$validators.empty = function(modelValue, viewValue) {
if (!ctrl.$isEmpty(modelValue)) {
return true;
}
return false;
}
}
};
});
.red-border {
border: 2px solid red;
}
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.12/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<form name="formName" ng-submit="onclick()">
<p>Hello {{name}}!</p>
<button type="submit">submit</button>
<ul>
<li ng-repeat="x in c">
<ng-form name="innerForm">
<input type="text" name="inputName" ng-model='x.name' empty-validator ng-class="{'red-border' : innerForm.inputName.$error.empty}" />
</ng-form>
</li>
</ul>
</form>
</div>
</body>
</html>
However, you asked for a weird request to validate it on a click of a button, so you might want to do it in the function itself. Which is not a proper way to validate it, but still can be done. Here is an example of that:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.name = 'World';
$scope.c = [{
name: 'abc'
}, {
name: 'pqr'
}];
$scope.d = [false, false];
$scope.onclick = function() {
var f = false;
for (var i = 0; i < $scope.c.length; i++) {
if (!$scope.c[i].name) {
$scope.d[i] = true;
f = true;
} else {
$scope.d[i] = false;
}
}
if (f) {
return false;
}
console.log($scope.c)
}
});
.red-border {
border: 2px solid red;
}
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.12/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<form ng-submit="onclick()">
<p>Hello {{name}}!</p>
<button type="submit">submit</button>
<ul>
<li ng-repeat="x in c">
<input type="text" ng-model='x.name' ng-class="{'red-border' : d[$index]}" />
</li>
</ul>
</form>
</div>
</body>
</html>
Related
I am working on Angularjs form validation for multiple input values.
Below is the issue I am facing
Let's say I entered 'Johnss', directive will validate and give error Invalid name
click on plus(+) button adjacent to Name label to add new Name input.
Enter Peter. Now you will see "Invalid name" for both Peter and Johnss.
Click on cancel button next to Peter.
Now in place of 'Johnss' try to enter any value and no validation is being done. Whatever value you enter it is accepting and no validation is happening.
Same is the case with 'Place' label.
What is the better way of doing this validation on each of the element?. Can someone please help me on this.
Also I am looking for a way to disable + button when validation fails.
Below is the code I have written
JS
var app = angular.module('multipleInputs',[]);
app.controller('multipleInputsCtrl',function($scope) {
$scope.users = [
{}
];
$scope.places = [{}];
$scope.addUser = function() {
var newUser = {};
$scope.users.push(newUser);
}
$scope.removeUser = function(user) {
var index = $scope.users.indexOf(user);
$scope.users.splice(index,1);
}
$scope.addPlace = function() {
var newPlace = {};
$scope.places.push(newPlace);
}
$scope.removePlace = function(place) {
var index = $scope.places.indexOf(place);
$scope.places.splice(index,1);
}
});
app.directive('nameValidation', function() {
var acceptableNames = ['John', 'Sachin', 'Sam', 'Sudhir', 'Nalanda'];
return {
require: 'ngModel',
link: function(scope, element, attr, mCtrl) {
mCtrl.$validators.name = function validationError(value) {
if (value && acceptableNames.includes(value)) {
return true;
} else if (value && !acceptableNames.includes(value)) {
return false;
} else {
return true;
}
}
}
};
})
app.directive('placeValidation', function() {
var acceptableNames = ['Chicago', 'Houston', 'Dallas', 'Seattle', 'Mumbai'];
return {
require: 'ngModel',
link: function(scope, element, attr, mCtrl) {
mCtrl.$validators.place = function validationError(value) {
if (value && acceptableNames.includes(value)) {
return true;
} else if (value && !acceptableNames.includes(value)) {
return false;
} else {
return true;
}
}
}
};
})
HTML
<!doctype html>
<html>
<head>
<title>Generate Multiple Input Fields Dynamically</title>
<link rel="stylesheet" href="styles.css" />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.8/angular.min.js"></script>
<script src="multipleInputs.js"></script>
</head>
<body ng-app="multipleInputs" class="users-container" ng-controller="multipleInputsCtrl">
<form name="myForm">
<div>
<div class="form-group">
<label for="inputName" style="color:darkblue">Name <button type="button" class="btn btn-sm" ng-click="addUser()">+</button></label>
<section ng-repeat="user in users">
<input class="users-container-inputs-text" type="text" placeholder="First Name" ng-model="user.name" name="personName" name-validation>
<span class="users-container-inputs-button" ng-click="removeUser(user)">X
</span>
<span class="alert-danger" ng-show="myForm.personName.$error.name"> Invalid name</span>
</input>
</section>
</div>
<div class="form-group">
<label for="inputPlace" style="color:darkblue">Place <button type="button" class="btn btn-sm" ng-click="addPlace()">+</button></label>
<section ng-repeat="place in places">
<input class="users-container-inputs-text" type="text" placeholder="Place" ng-model="place.name" name="placeName" place-validation>
<span class="users-container-inputs-button" ng-click="removePlace(place)">X
</span>
<span class="alert-danger" ng-show="myForm.placeName.$error.place"> Invalid place</span>
</input>
</section>
</div>
</div>
</form>
</body>
</html>
Codepen link:
https://codepen.io/sudhir_rocks/pen/ZEpKVrR
You can use ng-disabled Directive in AngularJS to disable HTML elements.
https://docs.angularjs.org/api/ng/directive/ngDisabled
If the expression inside the ng-disabled attribute returns true then the form field will be disabled.
I want to display checkboxes inside ng repeat. The checkboxes are not displayed. The checkboxes are not displayed at all. I am not understanding what the misatke is. Here is the code -
<div class = "col s4">
<form ng-submit="$ctrl.todoAdd()">
<input type="text" ng-model="$ctrl.todoInput" size="50" placeholder="Add New">
<input type="submit" value="Add New">
</form>
<br>
<div ng-repeat="x in $ctrl.todoList">
<input type="checkbox" ng-model="x.done"> <span ng-bind="x.todoText"></span>
</div>
<p><button ng-click="$ctrl.remove()">Remove marked</button></p>
</div>
And the javascript code-
angular.
module('dashboard').
component('dashboard', {
templateUrl: 'dashboard/dashboard.html',
controller: ['$routeParams','$http',
function dashboardController($routeParams,$http) {
this.todoList = [{todoText:'Clean House', done:false}];
this.todoAdd = function() {
this.todoList.push({todoText:this.todoInput, done:false});
this.todoInput = "";
};
this.remove = function() {
var oldList = this.todoList;
this.todoList = [];
angular.forEach(oldList, function(x) {
if (!x.done) this.todoList.push(x);
});
};
//Rest of the controller code
}
]
});
You need to have empty dependencies passed to your module while declaring,
change it as,
angular.
module('dashboard',[]).
DEMO
var app = angular.module('myFirstApp', []);
app.controller('myCtrl', function () {
this.todoList = [{
"todoText": "run today",
"done": false
},
{
"todoText": "read today",
"done": false
}];
});
<html>
<head>
<title>My First AngularJS App</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body>
<h1>My First AngularJS App</h1>
<div ng-app="myFirstApp" ng-controller="myCtrl as ctrl">
<div ng-repeat="x in ctrl.todoList">
<input type="checkbox" ng-model="x.done"> <span ng-bind="x.todoText"></span>
</div>
</div>
</body>
</html>
I am new to Angular JS, I created a div with input elements and I didn't use ng-model for input boxes.
<div class="row">
<br>
<div class="col-sm-10" id="rankingForm" >
<p ng-repeat=" x in $ctrl.outputProductAttributeValueList">
{{x}} <input type="text" />
</p>
<br>
<button type="submit" ng-click="$ctrl.onRankingFormSubmit()"> SUBMIT</button>
</div>
</div>
When I click on submit button I have to access all input values .Please help me how to do that .. I tried as below.
angular.module("productList")
.component("productList",{
templateUrl : "product-list/product-list.template.html",
controller : ["$http" ,"$scope","$document",function productListController($http,$scope,$document){
var self = this;
self.outputProductAttributeValueList =[ "age", "gender","all"];
self.onRankingFormSubmit = function () {
var queryResult = $document[0].getElementById("rankingForm")
console.log(queryResult);
// HERE queryResult is printing how to proceed further
};
}]
});
Now I want to collect all those input values dynamically created by ng-repeat. Please tell me how to do that ?
AngularJS ngModel is the standard approach for binding the view into the model instead of interacting directly with the DOM.
You can get all the inputs within the div id="rankingForm" you can do:
var inputs = $document[0]
.getElementById('rankingForm')
.getElementsByTagName('input');
Or by using Document.querySelectorAll():
var inputs = $document[0].querySelectorAll('#rankingForm input');
Once you have the inputs than iterate over all of them to get the values.. Notice that I have added attribute name to the inputs:
Code whitout ngModel:
angular
.module('App', [])
.controller('AppController', ['$scope', '$document', function ($scope, $document) {
$scope.outputProductAttributeValueList = ['age', 'gender', 'all'];
$scope.onRankingFormSubmit = function () {
var inputs = $document[0].querySelectorAll('#rankingForm input');
inputs.forEach(function(input) {
console.log(input.name + ': ' + input.value);
});
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular.min.js"></script>
<div ng-app="App" ng-controller="AppController" class="row">
<br>
<div class="col-sm-10" id="rankingForm" >
<p ng-repeat="x in outputProductAttributeValueList">
{{x}} <input type="text" name="{{x}}" />
</p>
<br>
<button type="submit" ng-click="onRankingFormSubmit()">SUBMIT</button>
</div>
</div>
Code with ngModel:
angular
.module('App', [])
.controller('AppController', ['$scope', '$document', function ($scope, $document) {
$scope.outputProductAttributeValueList = ['age', 'gender', 'all'];
// Model inputs
$scope.inputs = {};
$scope.onRankingFormSubmit = function () {
$scope.outputProductAttributeValueList.forEach(function(input) {
// Access to model inputs: $scope.inputs[input]
console.log(input + ': ' + $scope.inputs[input]);
});
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular.min.js"></script>
<div ng-app="App" ng-controller="AppController" class="row">
<br>
<div class="col-sm-10" id="rankingForm" >
<p ng-repeat="x in outputProductAttributeValueList">
{{x}} <input type="text" ng-model="inputs[x]" />
</p>
<br>
<button type="submit" ng-click="onRankingFormSubmit()">SUBMIT</button>
</div>
</div>
I'm Uploading files with AngularJS.
How to get the input files just like regular JS?
This is what I need to simulate exactly
HTML:
<input type="file" name="file" id="fileImg" accept="image/*">
JS:
var filesUpload = document.getElementById("fileImg").files
This is what I have now
HTML:
<input type="file" name="file" ng-model="image" accept="image/*">
<input type="button" ng-click="submit()" value="press me">
Angular:
angular
.module('app')
.controller("productsCtrl", function($scope) {
$scope.image = {};
$scope.submit = function() {
var filesUpload = ????????????????
}
}
So, how to get the "files" in the input withput using "getElementById" ?
notice - can't change nothing , only the "??????"
any help will be appreciated..
tnx
You can use custom directive
var app = angular.module('App', []);
app.controller('Main', function($scope, $timeout, $rootScope){
$scope.onSubmit = function(){
console.log($scope.file);
}
});
app.directive('fileRead', [function () {
return {
scope: {
fileRead: '='
},
link: function (scope, elem, attrs) {
elem.bind('change', function (event) {
scope.$apply(function () {
scope.fileRead = event.target.files[0];
});
});
}
}
}]);
usage
<div ng-app="App">
<div ng-controller="Main">
<form ng-submit="onSubmit()">
<input type="file" name="someName" file-read="file">
<button type="submit">Submit</button>
</form>
</div>
</div>
What changes need to be made to get the code below to successfully call the same validation directive from multiple different forms using AngularJS? Note that the first form is able to validate correctly, in that it checks for an even number of open parens ( and close parens ) and alerts the user immediately if the number is not equal.
However, when I try to get the second form to share the first directive, the second form fails to have the parens validation. And when I create a duplicate directive with a different name and call the duplicate directive from the second form, the second form's validation disables submit when there are unequal numbers of open and close parens BUT FAILS TO NOTIFY THE USER.
It seems silly to have redundant directives when the same validation will be used on many forms in a site.
This might (or might not) be complicated by the fact that each form is in a different include that is exchanged in the same index.html in a single-page web application. To rule out this possibility, I am including all the code required to reproduce the problem as follows:
index.html is:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>iPlotmy</title>
<link rel="stylesheet" type="text/css" href="resources/css/my.css">
</head>
<body ng-app="myApp">
<!-- build:js({app,.tmp}) scripts/main.js -->
<script src="js/lib/angular.js"></script>
<script src="js/lib/angular-resource.js"></script>
<script src="js/lib/angular-ui-router.js"></script>
<script src="js/lib/angular-ui-router-statehelper.js"></script>
<script src="js/lib/angular-animate.js"></script>
<script src="js/lib/angular-cookies.js"></script>
<script src="js/lib/angular-storage.js"></script>
<script type="text/javascript" src="myController.js"></script>
<div ng-controller="myController">
<table width=100%>
<tr>
<td colspan=3 align=center>
<table>
<tr>
<th>
<button ng-click="firstLink()">first link</button>
</th>
<th>
<button ng-click="secondLink()">second link</button>
</th>
</table>
</td>
</tr>
<tr>
<td>
<div ng-if="linktype == 'first'">
<div ng-include="'index_firstinclude.html'"></div>
</div>
<div ng-if="linktype == 'second'">
<div ng-include="'index_secondinclude.html'"></div>
</div>
</td>
</tr>
</table>
</div>
</body>
</html>
The index_firstinclude.html is:
<table>
<tr>
<td width=200>
<form name="userForm" ng-submit="firstForm(userForm.$valid)" novalidate>
<input type="text" name="func1" ng-model="firstplot.func1" required data-countparens=""/>
<p ng-show="userForm.func1.$error.required && !userForm.func1.$pristine" class="help-block">Function is a required field.</p>
<p ng-show="userForm.func1.$error.countparens" class="help-block">The number of open parentheses ( does not equal the number of close parentheses ) !</p>
<br>
<button type="submit" ng-disabled="userForm.$invalid" >Click to Submit</button>
</form>
</td>
</tr>
</table>
The index_secondinclude.html is:
<table>
<tr>
<td width=200>
<form name="mysecondForm" ng-submit="secondForm(mysecondForm.$valid)" novalidate>
<input type="text" name="func1" ng-model="secondplot.func1" required data-countparens=""/>
<p ng-show="mysecondForm.func1.$error.required && !mysecondForm.func1.$pristine" class="help-block">Function is a required field.</p>
<p ng-show="mysecondForm.func1.$error.countparenssecond" class="help-block">The number of open parentheses ( does not equal the number of close parentheses ) !</p>
<br>
theta min: <input type="text" ng-model="secondplot.tmin"/>
<br>
theta max: <input type="text" ng-model="secondplot.tmax"/>
<button type="submit" ng-disabled="mysecondForm.$invalid" >Click to Submit</button>
</form>
</td>
</tr>
</table>
The relevant parts of the myController.js file:
// create angular app
var myApp = angular.module('myApp', []);
// create angular controller
myApp.controller('myController', ['$scope', '$http', function($scope, $http) {
$scope.linktype = 'home';
$scope.firstplot = {type:"firstplot", func1: 'some (test) value'};
$scope.secondplot = {type:"secondplot", func1: 'another (test) value'};
$scope.firstForm = function(isValid) {
// check to make sure the form is completely valid
if (isValid) {
var funcJSON = {type:"firstplot", func1: $scope.firstplot.func1};
$http.post('/path/to/first-server-url', funcJSON).then(function(response) {
$scope.firstplot = response.data;
});
}
};
$scope.secondForm = function(isValid) {
console.log("inside secondForm")
if (isValid) {
$scope.secondplot.uri = "resources/images/plot-second-equation.gif";
var funcJSON = {type:"secondplot", func1: $scope.secondplot.func1};
$http.post('/path/to/second-server-url', funcJSON).then(function(response) {
$scope.secondplot = response.data;
});
}
};
//below functions handle navigation links
$scope.firstLink = function() {
$scope.linktype = 'first';
}
$scope.secondLink = function() {
$scope.linktype = 'second';
}
}]);
/// below directive(s) for form validation
myApp.directive('countparens', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$validators.countparens = function(modelValue, viewValue) {
return ctrl.$isEmpty(modelValue) ||
((modelValue.match(/\)/g) || []).length == (modelValue.match(/\(/g) || []).length);
};
}
};
});
myApp.directive('countparenssecond', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$validators.countparenssecond = function(modelValue, viewValue) {
return ctrl.$isEmpty(modelValue) ||
((modelValue.match(/\)/g) || []).length == (modelValue.match(/\(/g) || []).length);
};
}
};
});