This is a typical example of the use of ng-messages in AngularJS (1.x):
<form name="demoForm">
<input name="amount" type="number" ng-model="amount" max="100" required>
<div ng-messages="demoForm.amount.$error">
<div ng-message="required">This field is required</div>
</div>
<button type="submit">test submit</button>
</form>
see: http://jsfiddle.net/11en8swy/3/
I now want to change this example so the "This field is required" error only shows when the field is touched ($touched
) or the user hits the submit button.
I cannot use the ng-submitted
class on the form since the validation error prevents the submitting of the form.
How should I do this?
Thanks
You can do this using ng-show
:
<div ng-messages="demoForm.amount.$error" ng-show="demoForm.amount.$touched">
<div ng-message="required">This field is required</div>
</div>
And use a custom directive. See a working demo:
var app = angular.module('app', ['ngMessages']);
app.controller('mainCtrl', function($scope) {
});
app.directive('hasFocus', function($timeout) {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attr, ctrl) {
element.on('focus', function() {
$timeout(function() {
ctrl.hasFocusFoo = true;
})
});
element.on('blur', function() {
$timeout(function() {
ctrl.hasFocusFoo = false;
})
});
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-messages.js"></script>
<body ng-app="app" ng-controller="mainCtrl">
<form name="demoForm">
<input name="amount" type="number" ng-model="amount" max="100" required has-focus>
<div ng-messages="demoForm.amount.$error" ng-show="demoForm.amount.$touched || demoForm.amount.hasFocusFoo">
<div ng-message="required">This field is required</div>
</div>
<button type="submit">test submit</button>
</form>
</body>
The directive is basically setting another hasFocusFoo
field on the ngModel controller then we can easily use that directive.
Ah, at the PC at last.
https://plnkr.co/edit/EX3UmoAOKmTKlameBXRa?p=preview
<form name="mc.form">
<input type="text" name="empty" ng-model="mc.empty" required />
<label ng-show="mc.form.empty.$dirty && mc.form.empty.$error.required">i'm empty</label>
</form>
MainController.$inject = ['$timeout'];
function MainController($timeout) {
var vm = this;
$timeout(function(){
vm.form.$setPristine();
});
vm.submit = function(){
if(vm.form.$valid){
alert('yay');
}else{
(vm.form.$error.required || []).forEach(function(f){
f.$dirty = true;
});
}
}
}
Here is how I handle this task in my solution. form.$setPristine() - sets the field in a pristine
state, so field isn't $dirty
and error hidden. But after submit I manually state required fields in a $dirty
state, so errors become visible. + if you type something, and delete it after, the error would be visible without submitting a form.