validate dynamic form before submitting angular - angularjs

I'm dynamically creating forms with ng-repeat and they have some validation attributes (simplified version):
<div class="row" ng-repeat="defect in model.defects">
<form name="form_{{defect.id}}" novalidate>
<input ng-model="defect.name" required/>
<input type="submit" ng-click="saveDefect(defect)"/>
</form>
</div>
Basically what I want to do is this:
$scope.saveDefect = function (defect) {
if ($scope.<how to get the form name here>.$invalid) {
return;
}
}
Since the form name has been created dynamically with an id how do I access it? Other ways of doing the same are also welcome ofcourse :)

You can use the bracket notation to access it :
$scope["form_"+defect.id]
What I advise you to do is :
var app = angular.module("App", []);
app.controller("Ctrl", function($scope) {
$scope.forms = {};
$scope.list = [{id: 1}, {id: 2}];
$scope.save = function(item) {
if ($scope.forms["form_" + item.id].$invalid) {
alert("error on form_" + item.id);
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="App" ng-controller="Ctrl">
<div class="row" ng-repeat="item in list">
<form name="forms.form_{{item.id}}" novalidate>
<input ng-model="item.name" required/>
<input type="submit" ng-click="save(item)" />
</form>
</div>
</body>

Related

Writing an adding function in AngularJS

I'm new to AngularJS and I am doing some tutorials to get in touch with it. While I'm doing the tutorials I have modified the code a bit to get a better feeling of what's behind. My code consists of two parts, which have nothing to do with each other.
The first one is a simple user input and based on that a list gets filtered. This is working fine.
However, in the second part I was trying to implement a simple adding function where the user can give an input and based on that the sum of two numbers is calculated. This part is not working at all. The numbers are being recognised as strings. The code is basically from this source here. When I copy the whole code and run it, it works fine, but when I modify it a bit it doesn't.
I want to understand why my code isn't working. To me there is nearly no difference. So I think that I eventually misunderstood the concept of angularjs. But I can't figure out where the error could be.
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script type="text/javascript">
function TodoCtrl($scope) {
$scope.total = function () {
return $scope.x + $scope.y;
};
}
</script>
</head>
<body data-ng-app>
<input type="text" ng-model="name">{{name}}
<div data-ng-init="Names=['Arthur', 'Bob', 'Chris', 'David', 'EDGAR']">
<ul>
<li data-ng-repeat="naming in Names | filter: name ">{{naming}}</li>
</ul>
</div>
<div data-ng-controller="TodoCtrl">
<form>
<input type="text" ng-model ="x">{{x}}
<input type="text" ng-model ="y"> {{y}}
<input type="text" value="{{total()}}"/>
<p type= "text" value="{{total()}}">value</p>
</form>
</div>
</body>
</html>
Several things to change...
First you need to create a module:
var app = angular.module("myApp", []);
Then you need to define a module e.g. myApp on the ng-app directive.
<body data-ng-app="myApp">
Then you need to add TodoCtrl to the module:
app.controller("TodoCtrl", TodoCtrl);
Also check that both $scope.x and $scope.y have values, and make sure that they are both parsed as integers, otherwise you will get string concatenation ("1"+"1"="11") instead of addition (1+1=2)!
$scope.total = function () {
return ($scope.x && $scope.y)
? parseInt($scope.x) + parseInt($scope.y)
: 0;
};
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script type="text/javascript">
(function(){
var app = angular.module("myApp", []);
app.controller("TodoCtrl", TodoCtrl);
function TodoCtrl($scope) {
$scope.total = function () {
return ($scope.x && $scope.y)
? parseInt($scope.x) + parseInt($scope.y)
: 0;
};
}
}());
</script>
</head>
<body data-ng-app="myApp">
<input type="text" ng-model="name">{{name}}
<div data-ng-init="Names=['Arthur', 'Bob', 'Chris', 'David', 'EDGAR']">
<ul>
<li data-ng-repeat="naming in Names | filter: name ">{{naming}}</li>
</ul>
</div>
<div data-ng-controller="TodoCtrl">
<form>
<input type="text" ng-model ="x">{{x}}
<input type="text" ng-model ="y"> {{y}}
<input type="text" value="{{total()}}"/>
<p type= "text" value="{{total()}}">value</p>
</form>
</div>
</body>
</html>
As mentioned in the above two answers adding TodoCtrl as controller instead function will make the snippet work.
REASON:
Angularjs framework above 1.3 does not support global function which means declaring controller as function wont work.
In your code snippet, you are using angular version 1.5, which needs the controller to be defined.
DEMO
angular.module("app",[])
.controller("TodoCtrl",function($scope){
$scope.x = 0;
$scope.y = 0;
$scope.total = function () {
return parseInt($scope.x) + parseInt($scope.y)
};
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" >
<input type="text" ng-model="name">{{name}}
<div data-ng-init="Names=['Arthur', 'Bob', 'Chris', 'David', 'EDGAR']">
<ul>
<li data-ng-repeat="naming in Names | filter: name ">{{naming}}</li>
</ul>
</div>
<div data-ng-controller="TodoCtrl">
<form>
<input type="text" ng-model ="x">{{x}}
<input type="text" ng-model ="y"> {{y}}
<input type="text" value="{{total()}}"/>
<p type= "text" value="{{total()}}">value</p>
</form>
</div>
</div>
you need to define the TodoCtrl as controller instead function
.controller("TodoCtrl",function($scope){
$scope.x = 0;
$scope.y = 0;
$scope.total = function () {
return parseInt($scope.x) + parseInt($scope.y)
};
})
Demo
angular.module("app",[])
.controller("TodoCtrl",function($scope){
$scope.x = 0;
$scope.y = 0;
$scope.total = function () {
return parseInt($scope.x) + parseInt($scope.y)
};
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" >
<input type="text" ng-model="name">{{name}}
<div data-ng-init="Names=['Arthur', 'Bob', 'Chris', 'David', 'EDGAR']">
<ul>
<li data-ng-repeat="naming in Names | filter: name ">{{naming}}</li>
</ul>
</div>
<div data-ng-controller="TodoCtrl">
<form>
<input type="text" ng-model ="x">{{x}}
<input type="text" ng-model ="y"> {{y}}
<input type="text" value="{{total()}}"/>
<p type= "text" value="{{total()}}">value</p>
</form>
</div>
</div>

How to store values from a form to local storage in AngularJS?

I have some code for adding the values from a form to the local storage,
but when I tried the code, it is not running. I would like to store the form data in local storage by clicking the button. I am adding my sample code below:
App.controller('KeyController', function($scope,$localStorage) {
/*$scope.info = 'Welcome to Test';*/
/*console.log(" Key controller is working ");*/
$scope.api_url;
$scope.api_token;
$scope.submit=function(){
localStorage.setItem('api_url','--------');
localStorage.setItem('api_token','--------');
console.log(api_url);
console.log(api_token)
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="container">
<form role = "form" id="uriForm" name="authfrom">
<div class = "form-group">
<label for = "url">Enter the url to authenticate:</label>
<input type = "url" class = "form-control" placeholder = "Enter the URL" ng-model="api_url" required="required">
</div>
<div class = "form-group">
<label for = "Key">Enter the key here:</label>
<textarea class = "form-control" rows="5" placeholder = "Enter the Key" ng-model="api_token" required="required"></textarea>
</div>
<button class = "btn btn-default" ng-click="submit()">Explore!!</button>
<p class="warning">{{failed}}</p>
</form>
</div>
You haven't add your app.js file in html.
You didn't add your ng-app and ng-controller in html.
You were adding $localStorage in function which is not necessary.
You were using wrong syntax for localStorage.setItem()
Now I've edited your code and made this.
Here is index.html page
<!DOCTYPE html>
<html ng-app="app">
<head>
<title>App</title>
<script src="angular/angular.min.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body ng-controller="KeyController">
<div class="container">
<form>
<div class = "form-group">
<label for = "url">Enter the url to authenticate:</label>
<input type = "text" class = "form-control" placeholder = "Enter the URL" ng-model="api_url" required="required">
</div>
<div class = "form-group">
<label for = "Key">Enter the key here:</label>
<textarea class = "form-control" rows="5" placeholder = "Enter the Key" ng-model="api_token" required="required"></textarea>
</div>
<button class = "btn btn-default" ng-click="submit()">Explore!!</button>
<p class="warning">{{failed}}</p>
</form>
</div>
</body>
</html>
Here is your app.js file:
angular.module('app', [])
.controller('KeyController', function($scope) {
$scope.api_url;
$scope.api_token;
$scope.submit=function(){
localStorage.setItem('api_url', JSON.stringify($scope.api_url));
localStorage.setItem('api_token', JSON.stringify($scope.api_token));
console.log($scope.api_url);
console.log($scope.api_token)
}
});
You can copy paste this and check your self. First replace the reference of angular.min.js file.
Please go through the below code which has been corrected to bootstrap the angular module and set controller using ng-app and ng-controller.
Code snippets posted on stackoverflow cannot access localstorage for the reason mentioned here. So you'll need to run this code on your local development environment.
angular
.module('MyApp', []);
angular
.module('MyApp')
.controller('KeyController', [
'$scope',
function($scope) {
/*$scope.info = 'Welcome to Test';*/
/*console.log(" Key controller is working ");*/
$scope.api_url;
$scope.api_token;
$scope.savedApiUrl = '';
$scope.savedApiToken = '';
$scope.submit = function() {
localStorage.setItem('api_url', $scope.api_url);
localStorage.setItem('api_token', $scope.api_token);
var savedApiUrl = localStorage.getItem('api_url');
var savedApiToken = localStorage.getItem('api_token');
$scope.savedApiUrl = savedApiUrl;
$scope.savedApiToken = savedApiToken;
console.log($scope.savedApiUrl);
console.log($scope.savedApiToken)
}
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="container" ng-app="MyApp" ng-controller="KeyController">
<form role="form" id="uriForm" name="authfrom">
<div class="form-group">
<label for="url">Enter the url to authenticate:</label>
<input type="url" class="form-control" placeholder="Enter the URL" ng-model="api_url" required="required">
</div>
<div class="form-group">
<label for="Key">Enter the key here:</label>
<textarea class="form-control" rows="5" placeholder="Enter the Key" ng-model="api_token" required="required"></textarea>
</div>
<button class="btn btn-default" ng-click="submit()">Explore!!</button>
<p class="warning">{{failed}}</p>
</form>
<p>Saved values from local storage</p>
<p>API URL: {{savedApiUrl}}</p>
<p>API Token: {{savedApiToken}}</p>
</div>

How to handle multiple forms present in a single page using AngularJS

I am a newbie in AngularJS. I am having multiple forms on a single page which gets displayed based on the user selection only one at a time.
The DOM has two child controllers namely FirstFormController, SecondFormController wrapped under a parent controller named XceptionController.
A parent controller function is used to submit the form data from both the children. The form data is saved on to the parent controller's scope.My HTML looks like below
<div ng-app="app">
<div class="container" ng-controller="XceptionController">
<form class="form-container">
<select id="select-form" ng-change=selectForm() ng-model="selectedForm">
<option value="select" disabled selected>Select an Option</option>
<option value="firstform">Get Firstname</option>
<option value="secondform">Get Lastname</option>
</select>
</form>
<div ng-controller="FirstFormController" class="firstform" ng-show="fname">
<form name="firstnameform">
<input type="text" name="firstname" ng-model="form.firstname" id="firstname">
<label for="#firstname">Firstname</label>
</form>
<div class="content" ng-show="fname">
<p>Firstname is {{form.firstname}}</p>
</div>
</div>
<div ng-controller="SecondFormController" class="secondform" ng-show="lname">
<form name="lastnameform">
<input type="text" name="lastname" ng-model="form.lastname" id="lastname">
<label for="#lastname">Lastname</label>
</form>
<div class="content" ng-show="lname">
<p>Lastname is {{form.lastname}}</p>
</div>
</div>
<button ng-click="submitForm(form)">Submit</button>
And my js looks like
var app = angular.module('app', []);
app.controller('XceptionController', function($scope){
$scope.form = {};
$scope.selectedForm = '';
$scope.selectForm = function() {
$scope.lname = 0;
$scope.fname = 0;
var foo = angular.element(document.querySelector('#select-form')).val();
if(foo == 'firstform') {
$scope.fname = 1;
}
else if(foo == 'secondform'){
$scope.lname = '1';
}
};
$scope.submitForm = function(form){
//form data
console.log(form);
};
});
app.controller('FirstFormController', function($scope){
$scope.firstname = "";
});
app.controller('SecondFormController', function($scope){
$scope.lastname = "";
});
But on submitting the form I get the data from both the forms since I set it on the parent's scope. Is there a way by which I can submit the form and get the form data only for the form which is currently displayed. This fiddle will help you more in understanding my question. https://jsfiddle.net/xmo3ahjq/15/
Also help me in knowing if my code is properly written the way it should be or is there a better way to implement this. Should the form submission code be placed under a separate angular service ?
var app = angular.module('app', []);
app.controller('XceptionController', function($scope) {
$scope.form = {};
$scope.selectedForm = null;
$scope.selectForm = function() {
// reset the form model object
$scope.form = {};
};
$scope.isSelected = function(formName) {
return $scope.selectedForm === formName;
};
$scope.submitForm = function(form) {
// form data
console.log(form);
};
});
app.controller('FirstFormController', function($scope) {
});
app.controller('SecondFormController', function($scope) {
});
<div ng-app="app">
<div class="container" ng-controller="XceptionController">
<form class="form-container">
<select id="select-form" ng-change=selectForm() ng-model="selectedForm">
<option value="" disabled selected>Select an Option</option>
<option value="firstform">Get Firstname</option>
<option value="secondform">Get Lastname</option>
</select>
</form>
<div ng-controller="FirstFormController" class="firstform" ng-show="isSelected('firstform')">
<form name="firstnameform">
<input type="text" name="firstname" ng-model="form.firstname" id="firstname">
<label for="#firstname">Firstname</label>
</form>
<div class="content">
<p>Firstname is {{form.firstname}}</p>
</div>
</div>
<div ng-controller="SecondFormController" class="secondform" ng-show="isSelected('secondform')">
<form name="lastnameform">
<input type="text" name="lastname" ng-model="form.lastname" id="lastname">
<label for="#lastname">Lastname</label>
</form>
<div class="content">
<p>Lastname is {{form.lastname}}</p>
</div>
</div>
<button ng-click="submitForm(form)">Submit</button>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

angularjs get only selected checkbox

i want to get the selected checkboxes in my loop, for that check box i have to retrive the amount field onclick.
Here is my HTML script :
<div ng-repeat="$item in items">
Amount :<input ng-model="$item.daily_data.payment_amount">
Check : <input type=checkbox ng-model="checkAmount[$item.daily_data.id]" ng-value="$item.id" >
</div>
<input type="button" ng-click="checkNow()" />
The below script showing all check boxes . i want the only selected one.
JS Script :
$scope.checkAmount = {};
$scope.checkNow(){
console.log($scope.checkAmount);
}
First of all to use functions with $scope you should do something like this:
$scope.checkNow = function() {
...
}
or
$scope.checkNow = checkNow;
function checkNow() {
...
}
About your problem:
You could bind the checkboxes to a property (something like checked), so you can have the items that are checked easily in your controller.
Then, to calculate the total of all checked amount , I' suggest you to use Array.prototype.filter() + Array.prototype.reduce().
Here's a demo based on your original code:
(function() {
angular
.module("app", [])
.controller('MainCtrl', MainCtrl);
MainCtrl.$inject = ['$scope'];
function MainCtrl($scope) {
$scope.checkNow = checkNow;
$scope.checkAmount = {};
$scope.items = [
{
"id": 1
},
{
"id": 2
},
{
"id": 3
}
];
function checkNow() {
$scope.total = $scope.items.filter(function(value) {
return value.checked;
}).reduce(function(a, b) {
return a + b.amount;
}, 0);
}
}
})();
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
</head>
<body ng-controller="MainCtrl">
<div ng-repeat="$item in items">
<label>
Amount: <input type="number" ng-model="$item.amount">
</label>
<label>
Check: <input type=checkbox ng-model="$item.checked">
</label>
</div>
<button type="button" ng-click="checkNow()">Check now</button>
<hr>
<label for="total">Total</label>
<input type="number" id="total" disabled ng-model="total">
</body>
</html>

Angularjs repeat form fields

I've built a shopping cart for a training site. People can purchase a number of 'seats' for each training session. What I need to add is a form requiring the name and email for each seat(attendee). So if someone purchases 3 seats, then I will need to generate form fields for each attendee.
I'm assuming there's something in the following code that plays a part in solving this problem but I'm not skilled enough in Angular to work it out.
ng-repeat="i in quantity track by $index"
look at this codepen
it works fine :)
var app = angular.module('myapp',[]);
app.controller('ctrlParent',function($scope){
$scope.myNumber=1;
$scope.range = function(count){
var output = [];
for (var i = 0; i < count; i++) {
output.push(i)
};
return output;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp">
<div ng-controller="ctrlParent">
<input ng-model="myNumber" type="text" placeholder="Quantity"/>
<form ng-repeat="i in range(myNumber) track by $index">
<input type="text" placeholder="Name"/>
<input type="text" placeholder="Name"/>
<input type="text" placeholder="Name"/>
<input type="button" value="Ok"/>
</form>
</div>
</div>
First, get the number of seats, in the form (send the seats number by events OR shared service if the form are in another angular controller) So, let say $scope.nbrSeats (initial value = 0) in forms controller.
Second, using ng-repeat :
<form ng-repeat="i in nbrSeats">...</form>
Here is a working example for you:
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function($scope) {
$scope.quantity = '1';
$scope.availableQuantity = '10';
$scope.range = function(num) {
num = parseInt(num);
return new Array(num);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<form name="myForm">
<select ng-model="quantity">
<option ng-repeat="option in range(availableQuantity) track by $index">{{$index + 1}}</option>
</select><br/><br/>
<div ng-repeat="customer in range(quantity) track by $index">
Customer {{$index + 1}} name: <input type="text" ng-model="customer_$index"><br/>
</div><br/><br/>
<button type="submit">Purchase</button>
</form>
</div>

Resources