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

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/

Related

Setting a select with options in AngularJS

I'm sorry for disturbing, i'm having an issue with Angular.
Quite new to the framework, i'm trying to set a formulary with a select having options. But for some reason, in the html page, I have a list of countries but it's empty.
Could anyone give an hint on how to get through it please ?
Thanks in advance
<html>
<head>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/style.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- Latest Angular -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
</head>
<body>
<form class="form-horizontal">
<fieldset>
<!-- Form Name -->
<legend>NIF</legend>
<!-- Text input-->
<div class="form-group">
<md-input-container>
<label class="col-md-4 control-label" for="textinput">NIF</label>
<div class="col-md-4">
<input id="textinput" name="textinput" type="text"
placeholder="Entrer le NIF" class="form-control input-md"
required="" ng-model="data.nif">
</div>
</md-input-container>
</div>
<!-- Select Basic -->
<div class="form-group">
<label class="col-md-4 control-label">Pays</label>
<div class="col-md-4" ng-controller="countryController">
<select ng-model="selectedCountry" class="form-control"
ng-options="location as location.name for location in locations">
<!--<option ng-value="country" ng-repeat="country in countries"></option>-->
</select>
</div>
</div>
<!-- Select Basic -->
<div class="form-group">
<label class="col-md-4 control-label" for="Entité">Entité</label>
<div class="col-md-4">
<select id="Entité" name="Entité" class="form-control"
ng-model="data.entity">
<option value="Personne physique">Personne physique</option>
<option value="Personne morale">Personne morale</option>
</select>
</div>
</div>
<!-- Button -->
<div class="form-group">
<label class="col-md-4 control-label" for=""></label>
<div class="col-md-4">
<button id="" name="" class="btn btn-primary center-btn">Lancer la recherche</button>
</div>
</div>
</fieldset>
</form>
</body>
</html>
angular.controller('countryController', function($scope) {
$scope.locations = [
{ name: 'A' },
{ name: 'B' },
{ name: 'C' }
];
$scope.selectedCountry = { name: 'A' };
});
Correct the default selected reference.
So change $scope.selectedCountry = { name: 'A' }; to $scope.selectedCountry = $scope.locations[0];
Working Demo:
var myapp = angular.module('myapp', []);
myapp.controller('FirstCtrl', function($scope) {
$scope.locations = [{
name: 'A'
},
{
name: 'B'
},
{
name: 'C'
}
];
$scope.selectedCountry = $scope.locations[0];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp">
<fieldset ng-controller="FirstCtrl">
<select ng-options="location as location.name for location in locations" ng-model="selectedCountry"></select> {{ selectedCountry }}
</fieldset>
</div>
I just found out I could create multiple modules but not put more than one ng-app in the same page.
It's working perfectly now.

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 Validations for multiple fields

I need one example for validations on dynamic added fields. Here is my page.
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<link rel="stylesheet"
href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js">
</script>
<script
src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js">
</script>
<script
src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js">
</script>
<title>Add Remove in AngularJS</title>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.deleted = [];
$scope.inputs = [];
$scope.addRow = function(){
$scope.inputs.push({name:'', age:''});
};
$scope.removeRow = function(index, input){
// alert(index);
// alert(input);
$scope.deleted.push(input);
$scope.inputs.splice(index,1);
};
});
</script>
</head>
<body style="background-color: gray; margin-top: 10px; ">
<center>
<div class="row" ng-app="myApp" ng-controller="myCtrl">
<div class="col-md-6">
<div class="panel panel-flat">
<div class="panel-header">
<h4>
Person Address
<button ng-click="addRow()">Add</button>
</h4>
</div>
<div class="panel-body">
<form name="form" class="form-horizontal">
<div ng-repeat="input in inputs">
<div class="form-group" ng-class="{'has-error' : form.name.$invalid}">
<label class="col-md-2 control-label">Name</label>
<div class="col-md-10">
<input type="text" ng-model="input.name" name="name[$index]" ng-maxlength="45" ng-minlength="3"
class="form-control" ng-pattern="/^[a-zA-Z]+$/" required />
<span class="help-block" ng-show="form.name[$index].$error.pattern">Alphabet only</span>
<span class="help-block" ng-show="form.name[$index].$error.minlength">Too Short</span>
<span class="help-block" ng-show="form.name[$index].$error.maxlength">Too Long</span>
<span class="help-block" ng-show="form.name[$index].$error.required">required</span>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">Age</label>
<div class="col-md-10">
<input type="text" ng-model="input.age" name="age"
class="form-control" ng-pattern="/^[0-9]{0,3}$/" /><br>
<span ng-show="form.age.$invalid && form.age.$error.pattern">Number
length should be 3</span>
</div>
</div>
<button ng-click="removeRow($index, input)">Remove</button>
<hr>
</div>
</form>
</div>
</div>
</div>
<!-- inputs :{{inputs}}<br>deleted : {{deleted}} -->
</div>
</center>
</body>
</html>
You can add a fonction to you controller :
app.controller('myCtrl', function($scope) {
//...
$scope.validationFn = function () {
//do you validation here
};
then you just need to modify
<form name="form" class="form-horizontal" ng-submit="validationFn()">
Here is the answer:
<div class="panel-body"><form name="form" class="form-horizontal">
<div ng-repeat="input in inputs"><ng-form name="sfIn"><div class="form-group" >
<label class="col-md-2 control-label">Name</label>
<div class="col-md-10">
<input type="text" ng-model="input.name" name="name" ng-maxlength="45" ng-minlength="3"
class="form-control" ng-pattern="/^[a-zA-Z]+$/" required />
<span
class="help-block" ng-show="sfIn.name.$error.pattern">Alphabet only</span>
<span
class="help-block" ng-show="sfIn.name.$error.minlength">Too Short</span>
<span
class="help-block" ng-show="sfIn.name.$error.maxlength">Too Long</span>
<span
class="help-block" ng-show="sfIn.name.$touched.required || sfIn.name.$error.required ||
sfIn.name.$dirty.required">required</span>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label">Age</label>
<div class="col-md-10">
<input type="text" ng-model="input.age" name="age"
class="form-control" ng-pattern="/^[0-9]{0,3}$/" /><br>
<span
ng-show="sfIn.age.$error.pattern">Number
length should be 3</span>
</div>
</div>
<button
ng-click="removeRow($index, input)">Remove</button>
</ng-form>
<hr>
</div>
</form>
</div>

Error message not displayed on form submit when pristine

I have following code for form validation. It shows error messages when I enter some value in textbox (dirty) and the value is invalid. But when I do not make any change (pristine) and click submit, the error messages are not shown. How to fire error messages in this scenario?
Note: When I removed pristine check, the error message is displayed even before submitting.
<!DOCTYPE html>
<html>
<head>
<!-- bootstrap -->
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
<style>
body{padding-top: 30px;}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular-resource.js"></script>
<script type="text/JavaScript">
var myApp = angular.module('myApp', []);
myApp.controller('myController', function ($scope) {
//Call function on form submit
$scope.submitForm = function (isValid) {
if (isValid) {
alert('Valid');
}
else {
alert('Invalid');
}
};
});
</script>
</head>
<body ng-app="myApp" ng-controller="myController">
<div class="myDiv">
<div class="col-sm-8 col-sm-offset-2">
<div class="page-header">
<h1>Validation</h1>
</div>
<form name="userForm" ng-submit="submitForm(userForm.$valid)" novalidate>
<!-- Prevents HTML5 validation using novalidate-->
<div class="form-group" ng-class="{ 'has-error' : userForm.name.$invalid && !userForm.name.$pristine }">
<label>Name</label>
<input type="text" name="name" class="form-control" ng-model="user.name" required>
<p ng-show="userForm.name.$invalid && !userForm.name.$pristine" class="help-block">
Name required.</p>
</div>
<div class="form-group" ng-class="{ 'has-error' : userForm.location.$invalid && !userForm.location.$pristine }">
<label>Location</label>
<input type="text" name="location" class="form-control" ng-model="user.location"
ng-minlength="3" ng-maxlength="8">
<p ng-show="userForm.location.$error.minlength" class="help-block">
Location is less than min length.</p>
<p ng-show="userForm.location.$error.maxlength" class="help-block">
Location more than max length.</p>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</body>
</html>
Try using userForm.$submitted instead of $pristine
For a good learning exercise and debugging try the following in view
<pre>{{userForm|json}}</pre>

In Angularjs / Bootstrap why does my cancel button invoke the submit event

I have an Angular / Bootstrap form with a button type=submit and a plain button to cancel - and hide the form. When I click on the cancel, it calls the cancel event handler and then it calls the submit handler. ?? Here's the code as if have it in Plunker: http://plnkr.co/edit/Nsqy4DuVaoI04VObS2Zd?p=preview
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-example33-production</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.14/angular.min.js"></script>
</head>
<body ng-app="submitExample">
<script>
angular.module('submitExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.list = [];
$scope.text = 'hello';
$scope.cancel = function(){
alert('cancelling');
}
$scope.submitNewAccountForm = function(isValid){
alert('in submit');
}
}]);
</script>
<form ng-controller="ExampleController" name="newAccountForm" ng-submit="submitNewAccountForm(newAccountForm.$valid)" class="form-horizontal" novalidate>
<fieldset>
<!-- Form Name -->
<legend>Account</legend>
<!-- Text input-->
<div class="control-group">
<label class="control-label" for="name">Account name</label>
<div class="controls">
<input ng-model="name" id="name" name="name" type="text" placeholder="account" class="input-medium" required="">
<p class="help-block">Required.</p>
</div>
</div>
<!-- Select Basic -->
<div class="control-group">
<label class="control-label" for="type">Account type</label>
<div class="controls">
<select ng-model="type" id="type" name="type" class="input-medium">
<option>client</option>
<option>provider</option>
</select>
</div>
</div>
<!-- Button (Double) -->
<div class="control-group">
<label class="control-label" for="cancelaccountadd"></label>
<div class="controls">
<button type="submit" id="doaccountadd" name="doaccountadd" class="btn btn-success">Save</button>
<button ng-click="cancel()" id="cancelaccountadd" name="cancelaccountadd" class="btn btn-danger">Cancel</button>
</div>
</div>
</fieldset>
</form>
</body>
</html>
On button elements, submit is the default type attribute. change that to type="button" and it will no longer call the submit event.
Plunker

Resources