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>
Related
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/
For some reason Angular validation is not showing Html5 baloon/popups if we add two or more fields.
Please check these two examples:
Example with just one field. Press enter key to validate field and Html5 baloon/popup will show:
https://plnkr.co/edit/oKePef7p4O4AD59eWXe8?p=preview
Example with two fields. It doesn't show Html5 baloon/popup on field validation.
https://plnkr.co/edit/ZkDwB40Zhas3yjkT6AdM?p=preview
What is happening here!?
Thanks in advance.
In fact, none of your plnkrs are doing nothing, you're trying to use ngMessages module but you didn't put any kind of message error or anything.
Take a look on this simple demo:
(function(angular) {
'use strict';
angular.module('ngMessagesExample', ['ngMessages']);
})(window.angular);
<!DOCTYPE html>
<html ng-app="ngMessagesExample">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-messages/1.5.7/angular-messages.min.js"></script>
</head>
<body>
<form name="form">
<div class="col-md-12">
<div class="form-group" ng-class="{ 'has-error' : form.myName.$touched && form.myName.$invalid }">
<label for="name">Enter your name:</label>
<input type="text" class="form-control" name="myName" id="name" ng-model="name" ng-minlength="5" ng-maxlength="20" required />
<div class="help-block" ng-messages="form.myName.$error" ng-if="form.myName.$touched">
<p ng-message="required">This field is required</p>
<p ng-message="minlength">This field is too short</p>
<p ng-message="maxlength">This field is too long</p>
<p ng-message="required">This field is required</p>
<p ng-message="email">This needs to be a valid email</p>
</div>
</div>
<div class="form-group" ng-class="{ 'has-error' : form.myEmail.$touched && form.myEmail.$invalid }">
<label for="email">Enter your email:</label>
<input type="email" class="form-control" id="email" name="myEmail" ng-model="email" required />
<div class="help-block" ng-messages="form.myEmail.$error" ng-if="form.myEmail.$touched">
<p ng-message="required">This field is required</p>
<p ng-message="minlength">This field is too short</p>
<p ng-message="maxlength">This field is too long</p>
<p ng-message="required">This field is required</p>
<p ng-message="email">This needs to be a valid email</p>
</div>
</div>
</div>
</form>
</body>
</html>
I'd recommend you to check this tutorial to learn more about ngMessages.
I hope it helps!
I'm seeing weird flickering when mousing over the ng-clip enhanced button. I've got the ng-clip enhanced button being shown/hid when the enclosing div is moused over. As the user moves the mouse over the button, it flickers. I'm assuming it's something to do with event handling between Zeroclipboard and the Angular code?
Here is a Plunker page displaying the issue: http://plnkr.co/4gFy9U
The code from Plunker:
<!doctype html>
<html>
<head>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.14/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/zeroclipboard/2.1.6/ZeroClipboard.min.js"></script>
<script src="//rawgit.com/asafdav/ng-clip/master/src/ngClip.js"></script>
</head>
<body>
<div ng-app="myapp">
<div class="container" ng-controller="myctrl" ng-mouseover="isHovering = true" ng-mouseout="isHovering = false">
<div class="page-header">
<h1>ngClip <small>example</small></h1>
</div>
<form>
<div style="background:red;" class="form-group">
<label >Copy #1</label>
<input type="text" class="form-control" placeholder="Enter text to copy" ng-model="copy1">
<button ng-if="isHovering" class="btn btn-default" clip-copy="copy1">Copy!</button>
</div>
<br/><br/><br/>
<textarea class="form-control" rows="3" placeholder="paste here"></textarea>
</form>
</div>
</div>
<script>
var myapp = angular.module('myapp', ["ngClipboard"]);
myapp.config(['ngClipProvider', function(ngClipProvider) {
ngClipProvider.setPath("//cdnjs.cloudflare.com/ajax/libs/zeroclipboard/2.1.6/ZeroClipboard.swf");
ngClipProvider.setConfig({
bubbleEvents: false
})
}]);
myapp.controller('myctrl', function ($scope) {
$scope.fallback = function(copy) {
window.prompt('Press cmd+c to copy the text below.', copy);
};
$scope.showMessage = function() {
console.log("clip-click works!");
};
});
</script>
</body >
</html>
I was also having this issue. I fixed by using ng-mouseenter on an outer div instead of using ng-mouseover and ng-mouseleave on an inner div instead of ng-mouseout. No flicker!
So:
<div ng-app="myapp" ng-mouseenter="isHovering = true">
<div class="container" ng-controller="myctrl" ng-mouseleave="isHovering = false">
<div class="page-header">
<h1>ngClip <small>example</small></h1>
</div>
<form>
<div style="background:red;" class="form-group">
<label >Copy #1</label>
<input type="text" class="form-control" placeholder="Enter text to copy" ng-model="copy1">
<button ng-if="isHovering" class="btn btn-default" clip-copy="copy1">Copy!</button>
</div>
<br/><br/><br/>
<textarea class="form-control" rows="3" placeholder="paste here"></textarea>
</form>
</div>
</div>
I have a form using ng-messages for form validation error messages. Im also using the new ng-model-options with $rollbackViewValue to rollback all changes to the form. Problem is ng-mesages will not work if I use the rollbackViewValue on the form.
I really like this new function in angular1.3 using ng-model-options to reset a form as I have not found anything that works as well as $rollbackViewValue()
Heres is the code and plunker
<!DOCTYPE html>
<html data-ng-app="App">
<head lang="en">
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"/>
</head>
<body>
<div class="container" data-ng-controller="formCrtl as vm">
<div class="col-lg-5">
<form name="form" novalidate="novalidate" role="form"
data-ng-submit="vm.submit()"
data-ng-model-options="{updateOn: 'submit'}" >
<!---->
<div class="form-group" data-ng-class="{ 'has-error': form.fname.$invalid && form.fname.$touched }">
<label for="fname">First Name</label>
<input type="text" required class="form-control" name="fname" id="fname" placeholder="Enter text" data-ng-model="vm.names.fname">
<div data-ng-if="form.fname.$touched" data-ng-messages="form.fname.$error">
<span class="help-block" data-ng-message="required">required field</span>
</div>
</div>
<div class="form-group" data-ng-class="{ 'has-error': form.lname.$invalid && form.lname.$touched }">
<label for="lname">Last Name</label>
<input type="text" required class="form-control" name="lname" id="lname" placeholder="Enter text" data-ng-model="vm.names.lname">
<div data-ng-if="form.lname.$touched" data-ng-messages="form.lname.$error">
<span class="help-block" data-ng-message="required">required field</span>
</div>
</div>
<div class="col-sm-offset-2 col-sm-10 btn-group">
<button type="submit" class="btn btn-primary" data-ng-disabled="form.$invalid">Submit</button>
<button type="button" class="btn btn-default" data-ng-click="form.$rollbackViewValue()">reset</button>
<!---->
</div>
</form>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.8/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.8/angular-messages.js"></script>
<script src="scripts.js"></script>
</body>
</html>
controller
var App = angular.module("App", ['App', 'ngMessages']);
App.controller('formCrtl',function ($scope, $rootScope) {
var vm = this;
vm.names = {
fname: "Albert",
lname: "Capone"
}
});
You would need to make the form pristine and revert back the touched state as well. You can do so by calling the special functions, $setPristine() and $setUntouched() , on the formController. But it appears rollBackViewValue works with ngSubmit, but it is only to revertback during some action, (like esc key, another button). But if the form field has contraint errors it appears it updated viewvalue to nullify the entered value. You could try this way by resetting to default field values.
In your view:-
<button type="button" class="btn btn-default"
data-ng-click="vm.reset(form)">reset</button>
In your controller:-
var vm = this;
var defModel = {
fname: "Albert",
lname: "Capone"
};
vm.names = angular.copy(defModel);
vm.reset = function(form) {
form.$rollbackViewValue();
form.$setPristine(); //Set pristine state
form.$setUntouched(); //Set state from touched to untouched
vm.names = angular.copy(defModel); //reset model
}
var App = angular.module("App", ['App', 'ngMessages']);
App.controller('formCrtl', function($scope, $rootScope) {
var vm = this;
var defModel = {
fname: "Albert",
lname: "Capone"
};
vm.names = angular.copy(defModel);
vm.reset = function(form) {
form.$rollbackViewValue(); //Probably can be removed
form.$setPristine();
form.$setUntouched();
vm.names = angular.copy(defModel);
}
});
<div data-ng-app="App">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
<div class="container" data-ng-controller="formCrtl as vm">
<div class="col-lg-5">
<form name="form" novalidate="novalidate" role="form" data-ng-submit="vm.submit(form)" data-ng-model-options="{updateOn: 'submit'}">
<!---->
<div class="form-group" data-ng-class="{ 'has-error': form.fname.$invalid && form.fname.$touched }">
<label for="fname">First Name</label>
<input type="text" required class="form-control" name="fname" id="fname" placeholder="Enter text" data-ng-model="vm.names.fname">
<div data-ng-if="form.fname.$touched" data-ng-messages="form.fname.$error">
<span class="help-block" data-ng-message="required">required field</span>
</div>
</div>
<div class="form-group" data-ng-class="{ 'has-error': form.lname.$invalid && form.lname.$touched }">
<label for="lname">Last Name</label>
<input type="text" required class="form-control" name="lname" id="lname" placeholder="Enter text" data-ng-model="vm.names.lname">
<div data-ng-if="form.lname.$touched" data-ng-messages="form.lname.$error">
<span class="help-block" data-ng-message="required">required field</span>
</div>
</div>
<div class="col-sm-offset-2 col-sm-10 btn-group">
<button type="submit" class="btn btn-primary" data-ng-disabled="form.$invalid">Submit</button>
<button type="button" class="btn btn-default" data-ng-click="vm.reset(form)">reset</button>
<!---->
</div>
</form>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.8/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.8/angular-messages.js"></script>
</div>
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