I am trying to simply replicate the walkthrough from the Angular website but cannot get length validation to work:
<input
style="display:inline-block;min-width:150px"
class="form-input"
id="phone"
required
minlength="4"
maxlength="24"
type="number"
name="phone"
[(ngModel)]="client.phone"
#phone="ngModel" />
<!-- required works, minlength and maxlength always false -->
{{ phone.hasError('required') }} {{ phone.hasError('minlength') }} {{ phone.hasError('maxlength') }}
<div *ngIf="phone.errors && (phone.dirty || phone.touched)"
class="alert alert-danger">
<div [hidden]="!phone.errors.required">
Name is required
</div>
<div [hidden]="!phone.errors.minlength">
Name must be at least 4 characters long.
</div>
<div [hidden]="!phone.errors.maxlength">
Name cannot be more than 24 characters long.
</div>
</div>
I must be missing something simple, but for some reason the required validation changes depending on input, but both minlength and maxlength are always false regardless of how long my input is.
Its because number type doesnt have length property
There is a bug for this https://github.com/angular/angular/issues/15053
You can work around it like:
[ngModel]="client.phone" (ngModelChange)="client.phone = $event + ''"
Plunker Example
Update
Since in 4.2.0-beta.0 (2017-05-04) were introduced min and max validators so you can have a look https://github.com/angular/angular/pull/15813/commits/52b0ec8062381e7285b5f66aa83008edfbf02af3
Related
This is the code. I am using bootstrap valid and invalid classes to change input design once the length is valid and adding a feedback message.
When I run it the function doesn't work and the input field stays the same!
var name = document.getElementById("name");
var validFB = document.getELementById("valid-feedback");
var invalidFB = document.getElementById("invalid-feeback");
name.onblur = function lengthCheck() {
if (name.length > 1 && name.length < 20) {
name.classList.remove("form-control");
name.classList.add("form-control is-valid")
validFB.style.display = "block";
} else {
name.classList.remove("form-control");
name.classList.add("form-control is-invalid");
invalidFB.style.display = "block";
}
}
<div class="col-md-4">
<label for="validationServer01" class="form-label">First name</label>
<input type="text" class="form-control" id="name" required>
<div class="valid-feedback" style="display:none;">
Looks good!
</div>
<div class="invalid-feedback" style="display:none;">
Length should not exceed 50 characters.
</div>
</div>
<div class="col-md-4">
<label for="validationServer02" class="form-label">Last name</label>
<input type="text" class="form-control" id="name" required>
<div class="valid-feedback" style="display:none;">
Looks good!
</div>
<div class="invalid-feedback" style="display:none;">
Length should not exceed 50 characters.
</div>
</div>
There were multiple errors in your post.
Bad syntax
First, you were once using document.getELementById(..) instead of document.getElementById(..) (there was one upper L which cause syntax error)
You should read the documentation to better understand syntax and how it works.
Multiples Ids
In your code you were using the same ID value for multiple elements which may cause collision in the future.
An identifier is a name that identifies (that is, labels the identity of) either a unique object or a unique class of objects
I encourage you using different IDs for all of your HTML tags.
Input value
To check the input length, you were using name.length but, here name is an HTML element and not a string as you were expected.
To retrieve the value of an input you should use name.value and then use name.value.length to check the value.
Adding class names
You were trying to add multiple class names at once with classList.add(..) which cause the following error :
Failed to execute 'add' on 'DOMTokenList': The token provided ('class1 class2') contains HTML space characters, which are not valid in tokens.
Conclusion
Your snippets contains multiple error that you better handle one at the time. You should open you console when you're coding (with ctrl+f12) and check the error while you are coding.
EDIT
I also change name.onblur to name.addEventListener('blur',...) which is more easy to use in my opinion. You can check the documentation here !
let name = document.getElementById("firstName")
let invalidFB = document.getElementById("invalid-feedback-first-name")
let validFB = document.getElementById("valid-feedback-first-name")
name.addEventListener("blur",function(){
if (name.value.length > 1 && name.value.length < 20) {
name.classList.add("form-control");
name.classList.add("is-valid")
validFB.style.display = "block";
invalidFB.style.display = "none";
} else {
name.classList.remove("form-control");
name.classList.add("form-control");
name.classList.add("is-invalid")
invalidFB.style.display = "block";
validFB.style.display = "none";
}
})
<div class="col-md-4">
<label for="validationServer01" class="form-label">First name</label>
<input type="text" class="form-control" id="firstName" required>
<div class="valid-feedback" style="display:none;" id="valid-feedback-first-name">
Looks good!
</div>
<div class="invalid-feedback" style="display:none;" id="invalid-feedback-first-name">
Length should not exceed 50 characters.
</div>
</div>
<div class="col-md-4">
<label for="validationServer02" class="form-label">Last name</label>
<input type="text" class="form-control" id="lastName" required>
<div class="valid-feedback" style="display:none;">
Looks good!
</div>
<div class="invalid-feedback" style="display:none;">
Length should not exceed 50 characters.
</div>
</div>
I want to create custom rules for a form.
The example would be this:
<label class="form-label">Price range from</label>
<validation-provider rules="required_if:price_to" name="Price range from"
v-slot="{ errors }">
<input v-model="price_range_from" type="number"
ref="price_from">
<span class="validation-error form-span">{{ errors[0] }}</span>
</validation-provider>
</div>
<div class="ml-2 w-100">
<label class="form-label">Price range to</label>
<validation-provider name="Price range to"
v-slot="{ errors }">
<input v-model="price_range_to" type="number" class="form-control"
ref="price_to" name="price_range_to">
<span class="validation-error form-span">{{ errors[0] }}</span>
</validation-provider>
Out of this part of form I want to create a rule which has logic of this:
input of price_range_from is required if the price_range_to
field is not null.
input of price_range_from cannot be greater
then price_range_to.
And vice versa.
Script:
import {ValidationProvider, ValidationObserver, extend} from 'vee-validate';
import * as rules from "vee-validate/dist/rules";
import {required} from 'vee-validate/dist/rules';
Object.keys(rules).forEach(rule => {
extend(rule, rules[rule]);
});
extend('required', {
...required,
message: 'This field is required'
});
Tried to read the documentation on [https://logaretm.github.io/vee-validate/guide/forms.html]
But couldn't find the answer how to make custom rules.
Would be glad if someone showed and example that I could understand and move forward and make more custom rules.
You can do this by targeting other fields: https://vee-validate.logaretm.com/v3/advanced/cross-field-validation.html#targeting-other-fields
import { extend } from 'vee-validate';
extend('password', {
params: ['target'],
validate(value, { target }) {
return value === target;
},
message: 'Password confirmation does not match'
});
...
<ValidationObserver>
<ValidationProvider rules="required|password:#confirm" v-slot="{ errors }">
<input type="password" v-model="password">
<span>{{ errors[0] }}</span>
</ValidationProvider>
<ValidationProvider name="confirm" rules="required" v-slot="{ errors }">
<input type="password" v-model="confirmation">
<span>{{ errors[0] }}</span>
</ValidationProvider>
</ValidationObserver>
Read the docs to see more writing about how it works. Basically #confirm turns into target in the custom rule, and it corresponds to the name attribute on the input.
The validate function in the custom rule just returns a boolean for whether the field is valid or not, so you can add any custom logic in there and just make sure it returns a boolean.
In your case, it sounds like you want two different error messages, so you could consider making two custom rules.
I want to have a field in which users can type only numbers 0-9. In case they type other characters like '.' or 'e' it has to show an error that only positive natural numbers are allowed. Form is used in Angular.
So I have here the html form:
<div class="col-xl-8">
<input formControlName="money" type="number" class="form-control">
<span class="error" *ngIf="money?.errors?.pattern"> Natural numbers </span>
</div>
while pattern is
this.money = new FormControl('', [Validators.required, Validators.pattern('^[1-9][0-9]*$')]);
The pattern is just fine it allows numbers from 0 till 9 and it doesn't allow decimals or '.' or 'e'.
So the problem is that since input is type number it allows '.' and 'e' even though the pattern doesn't allow it and I can't submit it, the error message is not showed since the html validater is based on the type number thing.
Yet, inputs such as these are allowed and the error label does not appear:
1.....2
......
eeee........
1.0.0.01.0
And so on.
So what should I do to show the error label when '.' or 'e' are typed?
Use ng-pattern directive directly?
<div class="col-xl-8">
<input formControlName="money"
type="number"
ng-pattern="^[1-9][0-9]*$')]"
class="form-control">
<span class="error" *ngIf="money?.errors?.pattern"> Natural numbers </span>
</div>
And tie validation to $valid of that input myForm.myInput.$valid
Use following code:
<div class="col-xl-8">
<input [formControl]="money"
type="number"
class="form-control">
<span class="error" *ngIf="money.dirty && money?.errors?.pattern"> Natural numbers </span>
</div>
In your ts file update regex ^[1-9][0-9]{1,3}
Hope it will help
In .ts file :
export class ReactiveFormExampleComponent{
reactiveForm: FormGroup;
constructor(private fb: FormBuilder) {
this.reactiveForm = fb.group({
money: ['', [Validators.required, Validators.pattern('^[1-9][0-9]*$')]]
});
}
onSubmit() {
alert("Form submitted");
}
}
html file
<form [formGroup]="reactiveForm" (ngSubmit)="onSubmit()" nonvalidate>
<div>
<label class="center-block">Money:
<input type="number" class="form-control" formControlName="money">
</label>
<span [hidden]="reactiveForm.controls.money.valid || reactiveForm.controls.money.pristine" class="errorMsg">Natural numbers only</span>
</div>
<button type="submit" [disabled]="reactiveForm.invalid" class="btn btn-success">Save</button>
</form>
NOTE : Don't forget to import 'ReactiveFormsModule' in NgModule.
Here is working plunker check it out here.
I have such part of form:
<div ng-messages="submittedFrgPwd && forgotForm.username.$error" multiple>
<div ng-message="pattern">{{ 'INVALID_EMAIL' | translate }}</div>
<div ng-message="required">{{ 'EMPTY_EMAIL' | translate }}</div>
<div ng-message="minlength">{{ 'SHORT_EMAIL' | translate }}</div>
<div ng-message="maxlength">{{ 'LONG_EMAIL' | translate }}</div>
</div>
<input type="email" id="username-remember" name="username" ng-model="username" ng-minlength="8" ng-maxlength="200" required ng-pattern="email_regexp" ng-class="{ 'has-error': submittedFrgPwd && forgotForm.username.$invalid || submittedError}"/>
and for example:
when i enter email of normal length, but with invalid pattern i see only:
{{ 'INVALID_EMAIL' | translate }}
and this is normall.
but!
when i enter something like a#a.a i get both errors:
<div ng-message="pattern">{{ 'INVALID_EMAIL' | translate }}</div>
<div ng-message="minlength">{{ 'SHORT_EMAIL' | translate }}</div>
but is this real, to skip pattern messages until my min length is valid?
i try it so:
data-ng-show="submittedFrgPwd && forgotForm.username.$error.pattern && !forgotForm.username.$error.minlength && !forgotForm.username.$error.maxlength"
seems to work, but it's to ugly)
You could do this by specifieng , separated error, Its like AND operation which you are specifying minlength && pattern both error should occur.
Markup
<div ng-message="minlength,pattern">{{ 'INVALID_EMAIL' | translate }}</div>
Demo Plunkr
Update
Seems like ng-message="minlength,pattern" is not working, I'd suggest you to use alternative solution by using ng-if="!forgotForm.username.$error.minlength"
<form name="forgotForm" ng-controller="mainCtrl">
<label>
Enter your name:
<div ng-messages="submittedFrgPwd && forgotForm.username.$error" multiple>
<div ng-message="required">{{ 'EMPTY_EMAIL' }}</div>
<div ng-message="minlength">{{ 'SHORT_EMAIL' }}</div>
<div ng-message="maxlength">{{ 'LONG_EMAIL'}}</div>
<div ng-if="!forgotForm.username.$error.minlength" ng-message="pattern">{{ 'INVALID_EMAIL' }}</div>
</div>
<input type="text" id="username-remember" name="username"
ng-model="username" ng-minlength="8" ng-maxlength="200"
required ng-pattern="email_regexp"
ng-class="{ 'has-error': submittedFrgPwd && forgotForm.username.$invalid || submittedError}"/>
</form>
Update Plunkr
if you are seeing the handlers, it probably means there was an error somewhere. My best best is that ngMessages was not injected.
angular.module('app',['ngTranslate', 'ngMessages'])
Additionally, you could make use of angularjs form default to check for submission i.e. forgotForm.$submitted.
<div class="form-group" ng-class="{ 'has-error': forgotForm.$submitted && forgotForm.username.$invalid }">
You also do not need to use pattern for type=email unless there are some specific scenarios you want to test (e.g. email domain). ng-message='email' should be able to handle whether email is valid or not.
<div ng-message="email">{{ 'INVALID_EMAIL' | translate }}</div>
In any case, I have attached the plunker link below
http://run.plnkr.co/Em2eBprmn74FqSYu/
I have included bootstrap css which i found is helpful when validating (and change the html code a lil bit).
hope this helps.
I am using angularJS, and I'm trying to get an error to pop up if the input value is not a number.
Number Value: <input type="number" ng-model="mydata.number" ng-change="checkNumber()" />
<p style="color:red" ng-show="numberError">
{{ numberError }}
</p>
And then inside $scope.checkNumber I check to see if it's NaN:
if(!$scope.mydata.number || isNaN($scope.mydata.number)) {
$scope.numberError = "This must be a number";
}
It appears that when I initially enter a string such as "fff" no error popups up, and we don't enter the checkNumber function, but if I enter "1fff" then it does enter the function and the error shows like it should.
If the input type is number and the initial character is not a number, does the ng-model not change?
What about using the Angular built-in validation, like this:
<form name="myForm">
Number Value:
<input type="number" ng-model="mydata.number" name="myNumber" />
<p style="color:red" ng-show="myForm.myNumber.$dirty && !myForm.myNumber.$valid">
{{ numberError }}
</p>
</form>