angular 2: validate a input field with built in validators - javascript

Angular 2 has some built in validators like maxlength, minlength and pattern. i have written this line of code:
<input id="mobile" type="text" class="form-control" name="mobile"
minlength="10">
If a user enters for example a 5-digit number and goes to the next input field an error should appear that says like 'The number you have typed is incorrect'.
How to do that with Angular 2?
In angular 1 is very easy like this
<p class="help-block" ng-if="editForm.mobile.$error.minlength">
<h3>This field is required to be at least 10 characters.</h3>
</p>

If you're using template driven forms then you need to change your input to have an ngModel binding to a variable in your component, and a template variable name:
<input id="mobile" type="text" class="form-control" name="mobile" [(ngModel)]="mobileNumber"
#mobile="ngModel" minlength="10">
<div *ngIf="mobile.errors?.minlength">Minimum length not met</div>
That link in the comment on your question is very good reading for understanding this, as it has instructions such as
We set the name attribute of the input box to "mobile" so Angular can
track this input element and associate it with an Angular form control
called name in its internal control model.
We use the [(ngModel)] directive to two-way data bind the input box to
the hero.name property.
We set a template variable (#mobile) to the value "ngModel" (always
ngModel). This gives us a reference to the Angular NgModel directive
associated with this control that we can use in the template to check
for control states such as valid and dirty.
Here's a plunker you can muck about with: http://plnkr.co/edit/dxtIkZI1dhp07lvega5P

Related

A field of Angular template driven forms considered invalid even though the regExp matches

I have this input:
<div class="form-group">
<label for="power">Hero Power</label>
<input [(ngModel)]="model.powerNumber" name="powerNumber" type="text"
class="form-control" pattern="^[0-9]+$"id="powerNumber">
<div [hidden]="powerNumber.valid" class="alert alert-danger">
power must be a number
</div>
</div>
I have added a pattern validator to the input field (only number should pass the test). Below the input I have added an error message that should hidden when the input field is valid. However it shows even when I have entered a value that matches the pattern RegExp. What am I doing wrong?
Here is a Stackblitz demonstration https://stackblitz.com/edit/template-driven-form-demo-wl3apt?file=app%2Fuser-form%2Fuser-form.component.ts
add #powerNumber="ngModel" template reference to input ngModel and all will be working. It is already done with name input in your example
I don't know whether it is eligible for you, however you can use input just for numbers:
<input [(ngModel)]="model.powerNumber" name="powerNumber" type="number"
class="form-control" id="powerNumber">

Angular validators and ng-maxlength use

I've got the following div, which I want to add the bootstrap's class "has-error" if the input length is over 50 characters. This is the HTML:
<div class="form-group" ng-class="{has-error:[formData.titulo.$error]}">
<label for="inputTitulo">Título</label>
<input type="titulo" class="form-control" id="inputTitulo"
maxlength="50" ng-maxlength="50" ng-model="formData.titulo">
</div>
How can I make this work? I guess when you reach 50 characters, ng-maxlength throws a error, like the $error object, but I have no clue on what object is, how to access it, and if I have to do some more work in the controller or directive.
Any help here? I can't find any "easy" info regarding this issue and Angular validators.
edit 1:
I've seen all your responses, learned something new thanks to you, but this is still somehow not working. It currently is this way:
<div class="form-group" ng-class="{'has-error': formData.titulo.$error.maxlength}">
<label for="inputTitulo">Título</label>
<input type="titulo" class="form-control" id="inputTitulo" maxlength="50" ng-maxlength="50" ng-model="formData.titulo">
</div>
Also tested checking the length directly, as one of you suggested. But none of these solutions seem to work: it never adds the has-error class. Why?
To have the errors published on the scope, a form directive is required.
<div ng-form="form1" ng-class="{'has-error': form1.text1.$error.maxlength}">
<input name="text1" ng-model="formData.foo" ng-maxlength="50">
</div>
(Notice that the above uses the name attribute of the input to publish the form data - really, the ngModelController - on the scope)
So, the above works, and it's preferable if you do form validation. But, if you just need to check the length of some input, you don't have to use form validation - you could just check the model directly:
<div ng-class="{'has-error': formData.foo.length > 50}>
<input ng-model="formData.foo">
</div>
as you are using ng-model to make validations ,, this class ng-invalid will be added to your input
docs : https://docs.angularjs.org/api/ng/directive/ngModel
to use $error you need to access it using forms and names not ng-model ,, and the ng-class should be bound to the $error.maxlength not $error only
tutorial : https://scotch.io/tutorials/angularjs-form-validation
If you use the maxlength, a user will never be able to enter more characters than that, so you will never get the ng-maxlength error. It doesn't make sense to use maxlength and ngMaxlength together IMHO.
See the example on docs.angularjs.org/api/ng/directive/ngMaxlength (open the example in plunker and add maxlength attribute)

Require two words in textbox, with AngularJS

I really struggling with this. I need to force the user to write the first and last name, in only one textbox.
I using AngularJS, and I want to validate text field using ng-pattern. The field should accept all characters, and require 2 words.
This is input:
<input name="fistname_lastname" ng-model="fistname_lastname" ng-pattern='my_pattern' type="text">
I have the my pattern in the controller, like this:
$scope.my_pattern = /^\s*\w*\s*$/;
Is there another better way do it.
Yes, you can do it by directive too, but just for validating just text contains two characters or not ng-pattern would be better way to do.
Here your html would be using (.*?[a-zA-Z]){2,} this pattern.
HTML
<input type="text" ng-model="fistname_lastname" max-length="30"
ng-pattern="/^(.*?[a-zA-Z]){2,}$/" placeholder="add new todo here"/>
Working Fiddle
Update
If you want to stop your form from submitting,, then you need to no worry about it. Angular internally manages this for you. Whenever you mention ng-pattern against any form field, angular creates object for that field (field should have name and ng-model attribute), that object is responsible for the validity of particular field. As as ng-pattern regx doesn't gets satisfied, angular make that field as invalid, means it append ng-invalid-pattern & ng-invalid class. Resultant the form also gets invalid. and now if you can look at form object you will find that form gets invalid by using syntax form.$valid on html.
HTML
<form name="form" ng-submit="submit()">
<input type="text" ng-model="firstname_lastname" size="30" ng-pattern="/^(.*?[a-zA-Z]){2,}$/" placeholder="add new todo here"/>
<button type="submit">Submit</button>
</form>
Controller
$scope.submit = function(){
if($scope.form.$invalid) //here you can stop use from submitting for by checking validity
alert('Form is invalid'); //form is invalid
else
alert('Form is valid');//here you can do actual submit to server
}
Updated Fiddle
Hopefully this could help you, Thanks.
Thanks, for all your help. But what really worked was this regular expression.
\b([A-Z]{1}[a-z]{1,30}[- ]{0,1}|[A-Z]{1}[- \']{1}[A-Z]{0,1}
[a-z]{1,30}[- ]{0,1}|[a-z]{1,2}[ -\']{1}[A-Z]{1}[a-z]{1,30}){2,5}

Angular Custom Validation of Nested Attributes

I have an Angular-based form for which I want to apply specific validation:
<form name="createProject" novalidate>
<span ng-show="createProject.projectName.$invalid">Please enter a name for the project.</span></br>
<input type="text" ng-model="newProject.project.name" name="projectName" placeholder="Project Name" required>
<div ng-repeat="topic in newProject.project.topics_attributes">
<span>Topic {{$index + 1}}</span>
<input type="text" ng-model="topic.name" placeholder="Topic Name">
<input type="text" ng-model="topic.feed_size">
<div ng-repeat="topic_source in topic.topic_sources_attributes">
<span>Topic {{$parent.$index + 1}} Source {{$index + 1}}</span>
<select ng-model="topic_source.platform" ng-options="platform for platform in platforms" topic-source-required parent="$parent.topic.name">
<option value="">-- platform --</option>
</select>
<input type="text" ng-model="topic_source.keywords" placeholder="Topic Keywords" topic-source-required parent="$parent.topic.name">
<button ng-show="$last" ng-click="addTopicSource($parent.topic)">Add Topic Source</button>
</div>
</div>
<button ng-click="addTopic()">New Topic</button>
<input type="submit" ng-click="addProject()" ng-class="{ disabled: createProject.$invalid }" ng-disabled="createProject.$invalid" value="Add Project">
</form>
Back
In the form, a project can have either zero or multiple topics. Each topic must have at least one topic source. Basically, I want to create validation that checks if a topic is being added (added being defined as having a name) and if so require that it has at least one topic_source with platform and keyword fields entered associated with it.
Is this even possible? I'm not very familiar with Angular custom validation so I'm not sure how to begin implementing something like this.
**Edit**
Current progress on custom validation directive:
angular.module('dashboard').directive 'topicSourceRequired', ($parse) ->
require: "ngModel"
link: (scope, elem, attrs, ctrl) ->
topicName = $parse attrs.parent
scope.$watch topicName, (topicName) ->
ctrl.$parsers.unshift checkForExistence if topicName
checkForExistence = (topicSource) ->
if topicSource
ctrl.$setValidity "topicSourceRequired", true
else
ctrl.$setValidity "topicSourceRequired", false
topicSource
Ok, getting closer for this validation. Right now the validation seems to be checking if the two topic_source fields have values independent of whether or not the parent's name field has a value, AND the topic_source fields only register as invalid if a field has been entered and then erased.
How do I make sure the checkForExistence function is only called when topicName has a non empty string value? Second, how do I make sure blank fields are invalid without having to modify them somehow?
You need to create a custom directive that requires ngModel which gives you access to the ngModelController (look at the require option when creating a directive).
Basically, you can listen for changes to the value by registering with the $viewChangeListeners, read the current value from $viewValue, and set the validation through the controller function
$setValidity(validationErrorKey, isValid);
The validationErrorKey you set is the a boolean value on the $erros object of the controller.
Take a look at this page in the docs to get you going:
https://docs.angularjs.org/api/ng/type/ngModel.NgModelController

AngularJS typeahead tags

I'm using AngularJS typeahead, I made an autocomplete input with it, using custom templates (to add the photo and the name of the person that I'm typing) and it's working fine.
<input ng-model="data.friend"
typeahead="recipient as recipient.Name for recipient in loadStudents($viewValue)"
typeahead-template-url="/Content/js/inbox/partials/typeaheadTemplate.html"
typeahead-wait-ms="300"
typeahead-editable="false"
typeahead-min-length="1"
type="text" class="col_100 input radius2x transition boxsizing"
auto-focus />
But now I need it to be for more than one person, which means a tag-like system.
How can I do that with Angular typeahead?

Categories

Resources