AngularJS | Add / Remove Class Using Directive - angularjs

I'm new to AngularJS and needing help on how to toggle classes on form elements if the input is valid or invalid.
I have noted that most validation is done within the DOM - see here: https://scotch.io/tutorials/angularjs-form-validation
However, I'm wanting to avoid using the dom to handle validation. I want to use a custom directive to handle if a input is valid or invalid based upon validation rules.
Here is my HTML / Angular markup so far:
<fieldset ng-class="{error: loginForm.username.$invalid}">
<div class="form-input-error" ng-show="loginForm.$error">
Username is too short.
</div>
<div class="vfnz-fieldWrapper">
<input
type="text"
id="username"
ng-model="username"
class="vfnz-input--text"
placeholder="Username"
ng-minlength="3"
ng-maxlength="8" />
<label for="name" class="vfnz-input-label">
Username
</label>
</div>
</fieldset>
Here is a JSFIDDLE of my code so far
Basically when a input is invalid - add class to the fieldset. If the input is valid add class to fieldset.

from angular 1.3.x they came up with ng-messages ,i think you should try this. The advantages of using it is it will show the appropiate error if your input contains multiple error's.Add your class to the validation div
the below example checks for required and number .
<form name='cliForm'>
<input ng-model="vm.formData.newCreditLimit" type="text" name="changeCreditLimit" ng-pattern="/^[0-9]{1,15}$/" required />
<div class="highlight" ng-messages="cliForm.changeCreditLimit.$error" ng-if="cliForm.$submitted">
<div ng-message="required">* This field is required!</div>
<div ng-message="pattern">* Not a valid number!</div>
</div>
</form>
before using this include the ng-messages script since its in different module and inject the ng-messages to your angular module

I'm also looking for a solution to this issue, but the (lazy) answer I'm opting for right now is just to let some directives determine whether the element is valid or invalid, and just let angular handle the css classes. What I'm doing is to just add the ff to my css file:
.ng-invalid {
border-color: #e51c23;
color: #e51c23 !important;
}
.ng-error {
border-color: #e51c23;
color: #e51c23 !important;
}
.ng-valid {
border-color: #4CAF50;
color: #4CAF50 !important;
}

Related

How can make a label not visible as soon as a user types in an input using AngularJS?

I have a html as follows
<input ng-required="true" ng-model="Email" type="text" value="">
and i have a div as follows:
<div id="invalid" style="display: none">
<strong><i class="mycustomclass" ></i>Invalid</strong>
</div>
How can i make it that as soon as the user types in the input then the div is no longer visible or hidden using Angularjs. I know i need to use ng-show or hide but i cant seem to figure out how to put it together with the input ?
If you are using components it will look like this:
<div id="invalid" data-ng-hide="$ctrl.Email">
<strong><i class="mycustomclass" ></i>Invalid</strong>
</div>
If you are using old controller style:
<div id="invalid" data-ng-hide="Email">
<strong><i class="mycustomclass" ></i>Invalid</strong>
</div>

How to make Angular Forms ngModel classes inherit from Bootstrap Forms classes

I am using Bootstrap 4 to style my form controls, and want to use the Bootstrap Forms validation styles when Angular's ngModel adds CSS classes to forms, such as ng-valid, ng-invalid, ng-dirty, ng-pending.
For example, if I have the following form
<form novalidate>
<input type="email" class="form-control" ng-model="user.email" required />
</form>
and want to apply Bootstrap's .has-danger class when the control fails data validation with Angular (i.e. when ngModel adds the class .ng-invalid). How do I accomplish this or something to the effect of
input.ng-invalid {
/* inherit from bootstrap's
.form-control-danger */
}
I would use ng-class for applying the bootstrap classes. Bootstrap defines the styling of the classes once applied.
<form name='myForm'>
<input type="email" name='input' class="form-control" ng-model="user.email" ng-class="myForm.input.$valid ? '' : 'has-danger' " required />
//or get fancy with the object argument form of ng-class
... ng-minlength='3' ng-class="{
has-success: myForm.input.$valid,
has-warning: myForm.input.$error.minlength,
has-error: myForm.input.$error.required}"
Checkout: https://docs.angularjs.org/api/ng/directive/form
In Angular2 you can use the same approach as the #Tyler answer but with the new syntax.
<div
class="form-group"
[ngClass]="{ 'has-success': user.valid, 'has-error': user.invalid}"
>
<input
type="text"
class="form-control"
id="usr"
name="usr"
required
#user="ngModel"
[(ngModel)]="model.usr"
>
</div>
You create a new variable named user, line #user="ngModel", which contains the model state for user input. And with [ngClass]="{ 'class-name': bool-expression}" you assign classes when they expressions become true.
Have in mind that you need to put the classes names as strings if they aren't a valid JavaScript identifier (they have an - for example).

ngMessages with Angular 1.5.x Component

I just tried introducing ngMessages into my app that's using Components that were added in 1.5. As soon as I include any reference to ngMessage in my template I'm receiving this error message:
Error: $compile:ctreq Missing Required Controller.
This is a common error with ngMessages and the normal remedy is
suggested here:
https://docs.angularjs.org/error/$compile/ctreq?p0=ngMessages&p1=ngMessage
However, I'm using components, which are a special type of directive and this doesn't appear to be an option for components.
Has anyone gotten ngMessages to work within a component in 1.5?
The syntax for use with a directive is like this:
myApp.directive('myDirective', function() {
return {
require: 'ngModel',
...
}
}
The component documentation: https://docs.angularjs.org/guide/component doesn't cover an equivalent to require.
This might help you.
<form name="userLoginForm" autocomplete="off">
<input type="text" minlength="10" maxlength="10" ng-pattern="/^[0-9]+$/" required ng-model="userData.mobileNumber" placeholder="Enter Mobile Number" class="form-control login-form-input" id="mobileNumber" name="mobileNumberInput"/>
<div ng-messages="userLoginForm.mobileNumberInput.$error" role="alert">
<div ng-message="required">
This field is required
</div>
<div ng-message="pattern">
Enter correct mobile number
</div>
<div ng-message="minlength, maxlength">
Your mobile number must 10 characters long</div>
</div>
</div>
It happens when you don't have correct div structure.
First div has to include ng-messages, and one inside should be ng-message.
From Documentation:
<ANY **ng-messages**="expression" role="alert">
<ANY **ng-message**="stringValue">...</ANY>
</ANY>
Angular's debug message is unhelpful in this instance and cause more confusion.

Validate textarea with Angular ng-messages when using Tinymce (ui-tinymce)

How to validate using ng-messages like ng-maxlength when the <textarea> has a ui-tinymce attribute?
Or is there a better way?
<div class="form-group">
<div class="col-sm-12">
<label>Description</label>
<p class="small">Please provide as much detailed information as possible.</p>
<textarea name="description" class="form-control required" ui-tinymce="tinymceOptions" ng-model="aC.testData.description"
ng-maxlength="100" required></textarea>
<div class="help-block" ng-messages="mainForm.description.$error" ng-show="mainForm.description.$touched">
<p ng-message="required">A description is required.</p>
<p ng-message="maxlength">Description must not exceed 100 characters.</p>
</div>
</div>
</div>
The issue you are seeing is that the standard directives just count characters so a simple (empty) HTML sample:
<p></p>
Would indeed show as 7 characters when in reality there is no "visible" content. I built a custom directive for another editor and what I ended up doing is using jQuery's .text() function against the HTML. This removes all of the HTML tags and provides an approximation for the number of actual text characters in the editor. This is a portion of the code in the diective:
var jStrippedString = jQuery(modelValue).text().trim();
return (maxlength < 0) || ngModelCtrl.$isEmpty(jStrippedString) || (jStrippedString.length <= maxlength);
I believe that you would want to create a custom Attribute directive that allows you to grab the model data for the editor and perform this validation yourself.
Adding forced_root_block: "" to the tinymce options should also work. By default it will not add <p></p> from the start.

Required field Angularjs 1.2 and Bootstrap 3

With the changes to angularjs and bootstrap 3 I have been unable to create a form field that's required where the item will be surrounded with red highlight by only adding the required parameter to the input field. Here is a plunker with how I have it setup on my system and would expect it to work. I can't seem to find any documentation on bootstraps site about required either so that would really help if anyone can find that.
Plunker
EDIT: Replaced all the following with below comments ideas... I would still like a solution where I don't need to write any css and use Bootstrap 3.
My form field looks like this:
<body ng-app>
<div ng-controller="Controller" class="container">
<form novalidate class="simple-form" name="myForm">
<div class="form-group col-sm-4">
Name: <input type="text" ng-model="name" name="name" class="form-control" required/>
E-mail: <input type="email" ng-model="email" name="email" class="form-control" required/>
<small class="error"
ng-show="myForm.email.$error.required">
Your name is required.
</small>
</div>
</form>
</div>
</body>
Script.js Looks like this:
function Controller($scope) {
$scope.name = "Test";
$scope.email = "";
}
Style.css looks like this:
input.ng-invalid {
border: 1px solid red;
}
While this works it replaces the bootstrap css with the css above. I would much prefer to simply add in required to an element and not have to rewrite the css to add the hue and the animation.
I agree with both of the other two answers but would like to add more
I think your main problem is that Bootstrap 3 removed styling based on the :invalid and related pseudo-classes (see here for why). This is where the red outline in bootstrap 2.x came from.
Firstly, to fix your plunker you should:
Bootstrap your app with ng-app as Mike says
Put your input in a form with novalidate
Give a model to your input with ng-model so that it can be invalidated (by angular, using classes)
Move jQuery script include before bootstrap as it is a requirement of bootstrap.
Now you have a plunker where the correct classes are applied to indicate input validity. You won't yet have styling on these, but they won't depend on your browser's HTML5 form validation, so will work in anything angular supports.
To apply styling, you can either use straight CSS and apply it to the ng-valid, ng-invalid, ng-invalid-required etc classes, or you can use the ng-class suggestion from this comment to apply bootstrap's classes when you need them
ng-class="{'has-error': formname.inputname.$invalid}"
if you have named your input and wrapped it in a control.
Updated plunker: http://plnkr.co/edit/mE3dkG?p=preview
Edit
I had a go at making a directive for this too. It may be overkill, but this should work wherever you have a form-group class and add an ng-form to the same element
.directive('formGroup', function(){
return {
restrict: 'C',
require: '?form',
link: function(scope, element, attrs, formController){
if(!formController)
return;
scope.$watch(function(){
return formController.$valid;
}, function(valid) {
if(valid)
element.removeClass('has-error');
else
element.addClass('has-error');
});
}
};
});
Yet another plunker: http://plnkr.co/edit/UQjRrA?p=preview
* The email will not be valid unless it looks like an email
You have a couple of things missing here. First, in order for a form field to validate it needs a unique name:
<input class="form-control" type="text" name="test" required/>
Second, in order to disable stock HTML5 validation, you need to add a novalidate attribute to the form:
<form class="form-horizontal" name="myForm" role="form" novalidate>
Third, and most importantly, your example has no app or controller associated with it, so angular is completely ignoring it. That one you have to fix yourself.
Read more about angular forms here: http://docs.angularjs.org/guide/forms
I suggest you this excellent step by step : http://www.ng-newsletter.com/posts/validations.html

Resources