How to create an angular validation message directive - angularjs

I am new to angular and maybe trying to do the wrong thing.
What I am trying to, is to create a validation message directive, which can show validation message for a specific input field in a form. It should only show the validation message for required fields in case the input field is missing a value.
I've tried with the following HTML:
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<link rel="stylesheet" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<form name="myForm">
<input name="myInput" type="text" x-ng-model="object.input" required/><br/>
<span ng-show="myForm.myInput.$error.required" >Value required (working)</span><br/>
<span x-msg-required="myForm.myInput"></span>
</form>
</body>
</html>
and the JS:
var app = angular.module('myApp', []);
app.directive('msgRequired', function() {
return {
link : function(scope, element, attrs) {
element.text('Value required');
attrs.$set('ngShow', attrs.msgRequired + '.$error.required' );
}
};
});
The first span element with out directive shows the validation message as expected. The span element with my directive seems to always show the validation message. I am for sure not understanding the directives in angular. What am I missing or is there better ways of streamlining validation messages in angular?
There is a plunker: http://plnkr.co/edit/Gjvol8inw1DlWjHomZQw

I was also bothered by this with Angular and created a directive suite in AngularAgility called Form Extension to fix this very issue. It automatically generates validation messages for you based on whats on your element. It is also very configurable and even will generate labels for you if you'd like.
Consider normally having to type something like this to get validation:
<div ng-form="exampleForm">
<label for="firstName">First Name *</label>
<div>
<input type="text" id="firstName" name="firstName" ng-model="person.firstName"
ng-minlength="2" />
<div ng-show="exampleForm.firstName.$dirty && exampleForm.firstName.$error.minlength">
First Name must be at least 2 characters long.
</div>
</div>
</div>
That's a pain. With the plugin you can do something like this instead:
<div ng-form="exampleForm">
<div>
<input type="text" aa-auto-field="person.firstName" ng-minlength="2" />
</div>
</div>
Here are some relevant links:
Extensive demo
Blog post explaining it
Source on GitHub

So I see this is a couple months old, but in case anyone is looking for something that works:
I updated your Javascript to this:
var app = angular.module('myApp', []);
app.directive('msgRequired', function($compile) {
return {
//transclude: true,
restrict: "A",
link: function(scope, element, attrs) {
element[0].innerHTML = 'Value required in angular directive';
attrs.$set('ngShow', attrs.msgRequired + ".$error.required");
$compile(element)(scope)
}
};
});
which seems to work. I am however doing something VERY similar in another project, and getting an infinite compile loop :( Investigating that...
plnkr lives here.

Related

Why won't this ng-pattern filter numbers?

I have an AngularJS single page application. One view has a textbox that I want to only accept numbers for an integer field. I have entered this code in the controller and this textbox in the view, but when I run the view it accepts any keyboard characters. Can you tell me how I need to modify this to work?
$scope.FilterNumbersOnly = /^\d+$/;
<input ng-model="x.COLUMN_VALUE" ng-pattern="FilterNumbersOnly" />
From the AngularJS documentation, ng-pattern will set the pattern key on the error object when the values input into the text-based field do not pass the specified regex test.
This says nothing about prohibiting users from inputting text. If you would like to add that behavior, you need to listen to the pattern key on the error object and attach handlers to it. When the input is invalid, the error object will reflect this, and you should respond by preventing user input. Or you can take whatever such action you deem necessary.
To prevent user input, you can set the disabled attribute on the input field when the pattern key on the error object is set.
One simple way to accomplish this is with the ng-if directive.
<input disabled ng-if="!form.input.$valid" />
<input ng-if="form.input.$valid" />
Here is a link to a working example.
You can do it using:
ngChange directive;
ngMask module (Always I need handle inputs with masks I use it).
I made this snippet showing both ways:
(function() {
"use strict";
angular.module('app', ['ngMask'])
.controller('mainCtrl', function($scope) {
$scope.checkNumber = function() {
$scope.input = $scope.input.replace(/\D+/, '');
}
})
})();
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ngMask/3.1.1/ngMask.min.js"></script>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body ng-controller="mainCtrl">
<form name="form" novalidate>
<label for="withoutMask">Input without mask: </label>
<input type="text" id="withoutMask" ng-model="input" ng-change="checkNumber()">
<hr>
<label for="mask">Input with mask: </label>
<input type="text" id="mask" mask="d" repeat="15" restrict="reject" limit="false" ng-model="otherInput">
</form>
</body>
</html>
why not use the built-in HTML support?
<input type="number">
supported - http://caniuse.com/#search=input%20type%3D%22number%22

How to show a validationmessage on the validation of two fields and make the form invalid

I want to make a validation on the sum of two fields, both are numeric input, but the total must not be larger than 100.
So I thought I'd make a hidden input which reads the total from my controller, and create a custom validationdirective to check the value to be <= 100 and create a span which checks whether that input is valid or not and then show/hide it.
But the input is bound to a function (which adds the two fields together) on my controller, so I can not use ng-model.
So I thought I use ng-bind, but then my validation directive complained about this:
require: 'ngModel',, because I don't have a ng-model anymore.
So I deleted that require, but then the ctrl.$validators was not present anymore and that gave me an error....
And now I am lost :-)
My validationdirective is this:
angular.module(Config.name).directive('maxvalue', function () {
return {
require: 'ngModel',
link: function (scope, elm, attrs, ctrl) {
ctrl.$validators.maxvalue = function (modelValue, viewValue) {
//validation here
};
}
};
});
Can you give my a way to solve this?
EDIT
maybe my question is broader: I have more of these like alidations, where the validation is not tied to a single input field. I also have two buttons which a user can click (sort of a radio button, but then implemented with 2 buttons). I also want to show a span when no button is clicked + make the form invalid.
But I do not know how to say to the form 'you are invalid' neither from the form itself neither from the controller.
For set form or input valid\invalid you can use $setValidity.
But i recommend use special library use-form-error.
Example of using you can see on jsfiddle
angular.module('ExampleApp', ['use', 'ngMessages'])
.controller('ExampleController', function($scope) {
});
.errors {
color: maroon
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular-messages.min.js"></script>
<script src="https://cdn.rawgit.com/Stepan-Kasyanenko/use-form-error/master/src/use-form-error.js"></script>
<div ng-app="ExampleApp">
<div ng-controller="ExampleController">
<form name="myForm">
<label>Enter your digit 1:</label>
<input type="text" ng-model="digit1" name="myDigit1" />
<br>
<label>Enter your digit 2:</label>
<input type="text" ng-model="digit2" name="myDigit3" />
<div use-form-error="isGeaterHundred" use-error-expression="digit1*1+digit2*1>100" ng-messages="myForm.$error" class="errors">
<div ng-message="isGeaterHundred">Your sum is greated then 100</div>
</div>
<input type="submit" ng-disabled="myForm.$invalid">
</form>
</div>
</div>

Reset form to pre validation state?

We are new to angular and we wanted to use angular validations with our forms. We are using async ajax calls with a kendo grid to get, create, edit and save data without any submit. I am having a hard time figuring out how to reset the validation state of the form when the user chooses to create a new record.
I made this small exaple, trying anything I could find in sof without any luck so far:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.4/angular-messages.min.js"></script>
<div ng-app="app">
<div ng-controller="ValidationController">
<form name="myForm" novalidate>
<label>
Name
<input name="nombre"
ng-model="field"
required />
</label>
<div ng-messages="myForm.$error">
<div ng-message="required" ng-if="myForm.nombre.$touched" ng-messages-include="myMessages">
</div>
</div>
<button type="button" ng-click="reset(myForm);" value="Reset">reset validation</button>
</form>
<script type="text/ng-template" id="myMessages">
<div ng-message="required">required field</div>
</script>
</div>
</div>
<script>
angular.module('app', ['ngMessages']).controller("ValidationController", function ($scope, $window) {
$scope.reset = function (form) {
form.$setPristine();
form.$setUntouched();
form.$setValidity();
form.nombre.$setPristine();
form.nombre.$setValidity();
form.nombre.$setUntouched();
}
});
</script>
Here is my fiddle:
https://jsfiddle.net/yh9q1a2j/
Update:
I think this better suits your needs. I've updated the fiddle
https://jsfiddle.net/n7qqn1x6/6/
In your reset method call $setPristine along with clearing the formData object.
$scope.formData = {};
$scope.myForm.$setPristine();
To get the error messages to be removed from the page once added I had to use ng-show instead of ng-if
<div ng-show="myForm.nombre.$error.required&&myForm.nombre.$dirty">required</div>

angularjs get value from input in recursive template

How'd I get the value to controller from a nested view? I'd like to mention that I have a recursive approach.
HTML
<textarea ng-model="inputValue" class="ng-valid ng-dirty ng-valid-parse ng-touched"></textarea>
Full HTML structure can be found here
Edit:
I want to get the value of the textarea in my controller. (e.g. $scope.inputValue ); currently getting undefined
see this jszfiddle
http://jsfiddle.net/7qbucc62/
<div ng-app="app">
<div ng-controller="firstController">
<textarea ng-model="inputValue"></textarea>
<textarea ng-model="inputValue"></textarea>
</div>
</div>
<script>
(function abc()
{
var app=angular.module("app",[]);
app.controller("firstController",function($scope)
{
$scope.inputValue="";
});
})();
</script>
I think this is what you are asking
you can use $scope.inputValue directly in your controller. It will provide you the value of textarea

Work with multiple Forms and its values

Assume an certain amount of forms created by ng-repeat, which allows the user to sum something up like a+b and display the result instantly.
How would the Controller look like?
<div data-ng-repeat="form in forms">
<form name={{form.name}}>
<input type="text" name="a" ng-modal="?">
<input type="text" name="b" ng-modal="?">
</form>
<p>{{?.result}}</p>
</div>
The question marks within the html should be something unique I guess. And the controller may access something like an array of forms from scope ... but maybe someone has a suggestion
If I understand your question correctly and assuming you have defined the forms in an array for example, below code should work for you:
<!DOCTYPE html>
<html data-ng-app="formApp">
<head>
<script type="text/javascript" src="https://code.angularjs.org/1.2.26/angular.js"></script>
<script type="text/javascript">
var formApp = angular.module("formApp",[]);
formApp.controller("formController", function($scope)
{
$scope.forms = [{name: "Foo"}, {name: "Bar"}];
});
</script>
</head>
<body data-ng-controller="formController">
<div data-ng-repeat="form in forms">
<form name={{form.name}}>
<input type="text" name="a" data-ng-model="form.someField">
<input type="text" name="b" data-ng-model="form.someOtherField">
</form>
<p>{{form.someField + form.someOtherField}}</p>
</div>
</div>
</html>
So basically you were right when mentioning "array of forms from scope".
The important thing to know is that angular creates a new scope for every item in the collection when using ng-repeat. This means, you do not need to use unique member names. "form.someField" for example always references the member of the current scope.
The calculation you would like to perform could be done inline as in my example or you could move it to an own method on a "class" from which all items in the form collection will inherit.
By the way: it's "data-ng-model" and not "data-ng-modal" ;)

Resources