Error/Empty in triggering form.$invalid - angularjs

<form class="form-inline" name="form" novalidate>
<div class="sub-form" ng-form is-active ng-init="active = true" name="info">
<div class="col-md-4 col-sm-6 col-ie-4">
<div class="select-input">
<label for="xyz">Xyz *</label>
<i class="fa fa-check-circle success" ng-show="form.info.xyz.$valid"></i>
<i class="fa fa-spinner fa-spin"></i>
<i class="fa fa-times-circle error" ng-show="(form.info.xyz.$invalid && !form.info.xyz.$pristine)"></i>
<div class="styled-select">
<select
heights
name="xyz"
id="xyz"
ng-options="xyz.in as xyz.ft for xyz in xyzs"
ng-model="player.xyz"
required>
<option value="" selected="selected">-- Select --</option>
</select>
</div>
</div>
</div>
</div>
</form>
<div class="back-next-button-row">
<div class="red-button tiny-button next-button" ng-if="form.$valid">
<button ng-click="next()"><span class="button-text">Next</span><i class="fa fa-chevron-right"></i></button>
</div>
<div class="red-button tiny-button next-button" ng-if="form.$invalid">
<button ng-click="error()"><span class="button-text">Error</span><i class="fa fa-chevron-right"></i></button>
</div>
</div><!--back-next-button-row-->
In Script
$scope.form = {};
$scope.form.info = {};
$scope.formError = function () {
console.log($scope.form.info.xyz);
//Getting Object {}
}
While in html its showing proper objects that i expect
Basically I would like to check
if($scope.form.info.xyz.$invalid){
alert("Invlid")
}
I would be thankful if I came to know why this is creating problem in this prospect

With angular, you can do this inside the HTML and dont have to carry it to the script. If you want to check any form element is invalid or incomplete, you can add an element like this.
<p class="text-danger" ng-show="form.$invalid">Invalid</p>
If you still want to do on click, try the below.
In the HTML capture the form name on your function.
<button ng-click="next('form')">Validate</button>
In JS, you can have a function like the below,
$scope.next = function(form){
if ($scope[form].$valid) {
alert("True");
} else {
alert("Invalid");
}
};

Related

ng-model is not updating the right user in AngularJS

I am kind of new in AngularJS, and I have a form that users can edit there form. But when user clicks update, it updates the form. BUT, the user does not update the user. Shown in the image
Image here
Here is my code:
<div ng-controller="MyCtrl">
<div class="people-view">
<h2 class="name">{{people.first}}</h2>
<h2 class="name">{{people.last}}</h2>
<span class="title">{{people.title}}</span>
<span class="date">{{people.date}} </span>
</div>
</div>
</div>
<!-- the form -->
<div class="list-view">
<form>
<fieldset ng-disabled="inactive">
<legend>Basic Info</legend>
<b>First Name:</b>
<input type="text" ng-model="myObject.first">
<br>
<b>Last Name:</b>
<input type="text" ng-model="myObject.last">
<button type="button" class="edit" ng-show="inactive" ng-click="inactive = !inactive">
Edit
</button>
<button type="submit" class="submit" ng-show="!inactive" ng-click="update()">Update</button>
</form>
App.js
var app = angular.module("Portal", ['ngRoute']);
app.controller('MyCtrl', function($scope) {
$scope.inactive = true;
$scope.people = {};
$scope.myObject = JSON.parse(localStorage.getItem('myObject')) || {
first : $scope.people.first,
last : $scope.people.last,
};
$scope.update = function(){
$scope.people.first = $scope.myObject.first;
$scope.people.last = $scope.myObject.last;
localStorage.setItem('myObject', JSON.stringify($scope.myObject));
};
$scope.deletePeople = deletePeople;
function deletePeople(id){
var userToDelete;
$scope.people.forEach(function(p, index){
if(p.id == id){
userToDelete = index;
}
});
$scope.people.splice(userToDelete, 1);
console.log($scope.people);
}
});
List of users
<div class="people" ng-repeat="p in people | filter:userSearch" >
<a href="#/people/{{ p.id }}">
<img ng-src="{{p.img}}"/>
<span class="name">{{p.first}} </span>
<span class="name">{{p.last}} </span>
<p class="title">{{p.title}} </p>
<span class="date">{{p.date}} </span>
</a>
</div>
The people view section should be included under <div ng-controller="MyCtrl"> div. So just move that line up so it's the first line of the code.
Your ng-model in the form needs to be people.first and people.last respectively. E.g. <b>First Name:</b>
<input type="text" ng-model="people.first">
<br>
<b>Last Name:</b>
<input type="text" ng-model="people.last">
check this
As Swailem95 said you have to move the <div ng-controller="MyCtrl"> top and it looks like below after that.
<div ng-controller="MyCtrl">
<div class="people-view">
<h2 class="name">{{people.first}}</h2>
<h2 class="name">{{people.last}}</h2>
<span class="title">{{people.title}}</span>
<span class="date">{{people.date}} </span>
</div>
<!-- the form -->
<div class="list-view">
<form>
<fieldset ng-disabled="inactive">
<legend>Basic Info</legend>
<b>First Name:</b>
<input type="text" ng-model="myObject.first">
<br>
<b>Last Name:</b>
<input type="text" ng-model="myObject.last">
</fieldset>
<button type="button" class="edit" ng-show="inactive" ng-click="inactive = !inactive">
Edit
</button>
<button type="submit" class="submit" ng-show="!inactive" ng-click="update()">Update</button>
</form>
</div>
</div>

Angular validation for only 1 input field inside a form

I'm building a form using Angular 1.1.1 and Ionic.
There are many "wallets" and the user needs to send a new "value" to each of the wallet. My form has a validation for all fields which works fine when the 'submit' button for the form is pressed.
However, I also have a button next to each wallet to send only value to this wallet (not different values to all wallets). When I press it, all the validation errors appear, but I need error to be visible only for the particular wallet.
My form (index.html):
<form name="myForm" ng-submit="sendValues(wallets)" ng-controller="valuesCtrl" novalidate>
<div class="row" ng-repeat="wallet in wallets">
<div class="col item item-input-inset">
<label class="item-input-wrapper item-text-wrap">
<input name="wallet_{{wallet.id}}" type="number" ng-model="wallet.value" type="text" required/>
</label>
<span ng-show="myForm.wallet_{{wallet.id}}.$error.required">!!!</span>
</div>
<div class="col item">{{ wallet.previous }}</div>
<button ng-click="sendValue(wallet)">
<i class="ion-android-send"></i>
</button>
<span class=ng-show="myForm.$submitted==true && myForm.wallet_{{wallet.id}}.$error.required">Required</span>
</div>
<button class="button" type="submit">Submit</button>
</form>
My controller (values.js):
'Use Strict';
angular.module('App')
.controller('valuesCtrl', function($scope, $localStorage, UserService, $state) {
$scope.sendValues = function(wallets){
if ($scope.myForm.$valid) {
...
} else {
$scope.myForm.submitted = true;
}
},
$scope.sendValue = function(wallet){
if (wallet.value == null) {
$scope.myForm.submitted = true;
} else {
...
}
}
})
You need to create a form for each wallet
This is due to your html name attributes has same value inside ng-repeat
Use $index in your name field for differentiate all the name attribute.
<form name="myForm" ng-submit="sendValues(wallets)" ng-controller="valuesCtrl" novalidate>
<div class="row" ng-repeat="wallet in wallets">
<div class="col item item-input-inset">
<label class="item-input-wrapper item-text-wrap">
<input name="wallet_{{$index}}" type="number" ng-model="wallet.value" type="text" required/>
</label>
<span ng-show="myForm.wallet_{{wallet.id}}.$error.required">!!!</span>
</div>
<div class="col item">{{ wallet.previous }}</div>
<button ng-click="sendValue(wallet)">
<i class="ion-android-send"></i>
</button>
<span class=ng-show="myForm.$submitted==true && myForm.wallet_{{$index}}.$error.required">Required</span>
</div>
<button class="button" type="submit">Submit</button>
</form>
You have to create a form inside form again. But as per HTML standard you can not have nested form. But angular provided that ability to have nested form but the inner form should be ng-form. Which mean you are going to wrap form & inside that you can find multiple ng-form's.
So you should have ng-form="innerForm" which will keep track of each repeated form.
Other thing which I observed is, you did mistake while using ng-show(you had {{}} inside ng-show expression, which would not work). To fix it you could access object via its key like ng-show="innerForm['wallet_'+wallet.id].$error.required"
Markup
<form name="myForm" ng-submit="sendValues(wallets)" ng-controller="valuesCtrl" novalidate>
<div ng-form="innerForm" class="row" ng-repeat="wallet in wallets">
<div class="col item item-input-inset">
<label class="item-input-wrapper item-text-wrap">
<input name="wallet_{{wallet.id}}" type="number" ng-model="wallet.value" type="text" required/>
</label>
<span ng-show="innerForm['wallet_'+wallet.id].$error.required">!!!</span>
</div>
<div class="col item">{{ wallet.previous }}</div>
<button ng-click="sendValue(wallet)">
<i class="ion-android-send"></i>
</button>
<span class=ng-show="innerForm.$submitted==true && innerForm['wallet_'+wallet.id].$error.required">Required</span>
</div>
<button class="button" type="submit">Submit</button>
</form>

watching on the select item in Angularjs

I am having a div which contains a set of dropdown to select a criteria. We can add or delete criteria using the plus and minus buttons. The values to fill in the dropdown is fetched from an API.
The code for the UI is below:
<form novalidate="" role="form" name="filterForm" class="form-inline">
<div ng-repeat="criteria in criterias">
<div class="m-b">
<div class="form-group s-b" style="width: 150px;">
<span>Country</span>
<select class="form-control" ng-options="item for item in country" name="account" ng-model="criteria.country" style="max-width:100%"></select>
</div>
<div class="form-group s-b" style="width: 150px;">
<span>State</span>
<select ng-options="item for item in state" class="form-control" name="account" ng-model="criteria.state" style="max-width:100%"></select>
</div>
<div class="form-group s-b" style="width: 150px;">
<span>City</span>
<select class="form-control" ng-options="item for item in city" name="account" ng-model="criteria.city" style="max-width:100%;"></select>
</div>
<div class="form-group s-b" style="width: 150px;">
<span>Predicate</span>
<select class="form-control" name="account" ng-model="criteria.predicate" style="max-width:100%">
<option value="matches">Matches</option>
<option value="not-matches">Not Matches</option>
</select>
</div>
<div class="form-group s-b" style="width: 100px;">
<span>Value</span>
<select class="form-control" ng-options="item for item in value" name="account" ng-model="criteria.value" style="max-width:100%;"></select>
</div>
<div class="form-group s-b" style="margin-top: 20px;">
<span>
<button class="btn btn-sm btn-primary pad-btn" type="submit" ng-click="addCriteria()">
<i class="fa fa-plus"></i>
</button>
<button class="btn btn-sm btn-danger pad-btn" type="submit" ng-click="deleteCriteria(criteria)">
<i class="fa fa-minus"></i>
</button>
</span>
</div>
</div>
</div>
<button class="btn btn-sm btn-primary pad-btn align-center" type="submit" ng-click="searchParams(filterForm)">Submit
<i class="fa fa-check"></i>
</button>
<button class="btn btn-sm btn-warning pad-btn align-center" type="submit" ng-click="resetFilter()">Reset
<i class="fa fa-reply"></i>
</button>
</form>
I need to watch for the dropdown and handle the event for the corresponding criteria and update the other corresponding dropdown elements for that criteria. Please let me know how to handle the $watch element when there are many criterias when user has added using the plus button as I am not advanced programmer on AngularJs.
Updated Question
Based on the suggestion I have used the ng-change instead of $watch and I am now able to handle the event and also get the reference to the criteria object. After handling the event, I need to update the state value for the selected country. I have updated the Plnkr link with the code below but the state drop down is not getting updated even after updated the scope using $scope.criterias[index] = user;. Please let me know if I am missing something.
Updated code to handle the change event:
$scope.handleClassification = function(index){
var user = $scope.criterias[index];
user.config=["California"];
$scope.criterias[index] = user;
console.log(user);
}
I am providing the updated plnkr link for more details - Plnkr
Try this way..I guess you want to update select in a cascade way...
Your HTML file:
<div ng-controller="StaticCtrl">
<h1>Static - Oriented</h1>
<p>This approach may be better when you have the entire dataset</p>
<div>
Country:
<select id="country" ng-model="cities" ng-options="country for (country, cities) in countries" ng-change="onChange()">
<option value=''>Select</option>
</select>
</div>
<div>
State: <select id="city" ng-disabled="!cities" ng-model="suburbs" ng-options="city for (city, suburbs) in cities"><option value=''>Select</option></select>
</div>
<div>
City: <select id="suburb" ng-disabled="!suburbs" ng-model="suburb" ng-options="suburb for suburb in suburbs"><option value=''>Select</option></select>
</div>
</div>
and your JS:
function StaticCtrl($scope) {
$scope.countries = {
'India': {
'UP': ['Noida', 'Lucknow', 'Agra'],
'Maharashtra': ['Mumbai']
},
'USA': {
'San Francisco': ['SOMA', 'Richmond', 'Sunset'],
'Los Angeles': ['Burbank', 'Hollywood']
},
'canada': {
'People dont live here': ['igloo', 'cave']
}
};
$scope.onChange = function() {
console.log("Asdasd");
$scope.suburb = '';
}
}
Here is the fiddle..

Cannot read property '$valid' of undefined

I have a form with a name field and two validations - required and max-length.
When I enter correct value, the form in controller is showing valid and returning true. But on entering wrong data, $valid is not throwing false and simply says -
Cannot read property '$valid' of undefined
Why is the form getting undefined in this case?
Jsfiddle here
Thanks in advance
Add ng-submit attribute to the form:
<form name="myForm" ng-submit="SaveAndNext()" novalidate>
Change controller to:
function myCtrl($scope, $log){
$scope.data = {};
$scope.SaveAndNext = function(){
if($scope.myForm.$valid){
$log.info('Form is valid');
$log.info($scope.data);
} else {
$log.error('Form is not valid');
}
}
}
Remove ng-click event handler from your submit button
Updated fiddle: http://jsfiddle.net/9cgopo7d/1/
I included the $log service because it's a useful default service and you might not know about it.
See demo below pass your form to controller with the submit click
ng-click="SaveAndNext(myForm)"
and now you can easy access all your form properties
function myCtrl($scope) {
$scope.SaveAndNext = function(form) {
console.log(form);
if (form.$valid) {
alert(form.$valid);
} else {
alert("!" + form.$valid)
}
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="registrationdetails" ng-app="" ng-controller="myCtrl">
<form name="myForm" novalidate>
<div class="list">
<div class="item list-item">
<div class="row row-center">
<div class="col-50"> <span class="form-field-name">Name</span>
</div>
<div class="col-50">
<textarea type="text" rows="5" ng-model="data.Name" name="Name" ng-maxlength=45 required></textarea> <span ng-show="myForm.Name.$dirty && myForm.Name.$invalid">
<span class="form-error" ng-show="myForm.Name.$error.required">Name is required</span>
<span class="form-error" ng-show="myForm.Name.$error.maxlength">Name should be max 45 characters</span>
</span>
</div>
</div>
</div>
<div class="item list-item">
<div class="row row-center">
<div class="col-50"> <span class="form-field-name">Type</span>
</div>
<div class="col-50">
<select ng-class="{defaultoption: !data.Type}" ng-model="data.Type" name="Type" required>
<option value="" disabled selected class="defaultoption">Type</option>
<option value="1" class="actualoption">Type 1</option>
<option value="2" class="actualoption">Type 2</option>
</select>
<span ng-show="myForm.Type.$dirty && myForm.Type.$invalid">
<span class="form-error" ng-show="myForm.Type.$error.required">Type is required</span>
</span>
</div>
</div>
</div>
<div class="item list-item">
<div class="row">
<div class="col">
<input type="submit" class="button" ng-click="SaveAndNext(myForm)" value="Next">
</div>
</div>
</div>
</div>
</form>
</div>
Place $scope.data={}; at the top of controller:-)
This is happening becuase you are directly submit the form which doesn't yet initialized the data object and therefore name data.Name is not recognized.
And if you place $scope.data={} in that case we have empty data object initialized.So in second case we have atleast reference of empty object whereas in first case it doesn't have any reference.
Fiddle
HTML:
<form name="form" id='form' novalidate>
<input type="text"required name="Title" ng-model="Title">
<div ng-messages="form.Title.$error">
<div ng-message="required">Field Required</div>
</div>
</form>
JS:
$scope.save= function(){
if (!scope.createMessage.$valid) {
scope.form.$submitted = true;
return;
}
The format for using $valid should be like this. If you don't get again then visit the official site of AngularJs.
I had similar problem, but in my case I was a ng-if creating a child scope that did not have the form defined.
Just changed the ng-if to ng-show and the form stop be undefined.

Having issues sending scope to the template in AngularJS

MY issue is this:
When I request the data from the server this sent the data correctly but in LoginController after doing the validation I'm trying to populate the user's username and email but those variables are not being printed in the template. However if I just send those variables in a simple JSON such as $scope.details = [{ 'username':'Karman', 'username':'karman#mail.com'}]; it's working fine, what am I doing wrong? Is there some issue with ng-repeat directive?
Thanks in advance to whom can help me out with this issue.....
ps: I'm using sillex and ng-resource just in case
<body ng-controller="LoginController">
<div class="col-xs-3 details-user">
<div class="col-xs-1">
<img src="web/img/avatar.jpg" alt="..." class="img-circle">
</div>
<div class="col-xs-2">
<ul>
<li ng-repeat="detail in details">
{{detail.username}} -- {{detail.email}}
</li>
</ul>
</div>
</div>
Controller:
function LoginController($scope, Login) {
var currentResource;
$scope.login = function () {
Login.query({email: $scope.email}, function success(data){
$scope.details = data;
//$scope.details = [{ 'username':'Karman', 'username':'karman#mail.com'}];
});
}
}
Form:
<!-- Main DIV -->
<div id="login" class="login-main">
<div class="form-wrap">
<div class="form-header">
<i class="fa fa-user"></i>
</div>
<div class="form-main">
<form>
<div class="form-group">
<input ng-model="email" type="text" class="input-large" placeholder="Tu email aqui..." required>
<input ng-model="password" type="password" class="input-large" placeholder="Tu password aqui..." required>
</div>
<button ng-click="login()" ng-show='addMode' class="btn btn-success">Sign In</button>
</form><!-- end form -->
</div><!-- end div form-main -->
<div class="form-footer">
<div class="row">
<div class="col-xs-7">
<i class="fa fa-unlock-alt"></i>
Forgot password?
</div>
<div class="col-xs-5">
<i class="fa fa-check"></i>
Sign Up
</div>
</div>
</div>
</div>
</div>

Resources