issues with ngPattern directive - regex

I've this code:
<form name="test">
<input type="text" ng-model="code" name="code" ng-pattern="/^code_[0-9]+$/"/>
<div ng-show="test.code.$dirty && test.code.$invalid">
Error:
<span ng-show="test.code.$error.pattern">Pattern fail.</span>
</div>
</form>
I have 2 issues with this code:
Strings like " code_232 ", "code_232 " " code_232" pass the validation. I'm not expert with regex, so this could be an issue simply related to the regex i wrote: /^code_[0-9]+$/
If i start writing "code_23892" (a correct string), i get the error
message while i'm still writing (test.code.$error.pattern = true). Is there a built-in way to avoid this? So my desidered behaviour is:
If i write "cod", and the input has still focus: no error
If i write "cod" and the input loses focus: error.
If i write "a", "ca", "coa" etc.: error, cause the pattern is already violated.
Is this already possible, or i've write a custome validation directive to achieve this?
Thanks in advance.

The reason that whitespace doesn't trigger a failed validation is because ng-model automatically trims the value. If you don't want that, you can add ng-trim="false" to your <input />. Note that ng-trim is a quite new attribute, so you might have to update your Angular version.
About your second question; I don't think you can avoid the validation to run during the time you type, but you could change your code to only display the error when the input looses focus. I don't think that something like ng-blur and ng-focus exists, but it should be pretty simple to implement them.

Related

Angular2 - Why does my reactive form input with an html pattern attribute is not validating correctly?

I'm struggling with a problem that I can't understand:
I need to validate an input field with a pattern="[0-9]+([,.][0-9])?" attribute on an angular reactive form with Validators.pattern, but it seems my ? quantifier at the end is not working...
What I want
I want to validate numbers with zero or one decimal maximum. As you can see on https://regex101.com/r/2D2sww/1, the regex is working great.
The actual problem
In my app I can enter as many decimals as I want without the Validator.pattern to do anything. Any other character invalidate the form, so my Validator is working.
Here is my code (simplified):
component.html
<form [formGroup]="myForm">
<input type="number" formControlName="myInputField" id="myInputField" pattern="[0-9]+([,.][0-9])?" required />
</form>
component.ts (Every import and declarations are skipped for clarity)
ngOnInit() {
this.myForm = this.formBuilder.group({
myInputField: [
"",
[Validators.required, Validators.pattern],
]
});
}
I already tried to use Validators.pattern(/^[0-9]+([,.][0-9])?$/) and Validators.pattern("[0-9]+([,.][0-9])?") as pointed in the documentation, but it doesn't change anything, so I suspect my Regex to be incorrect...
Any ideas ? Thanks, have a nice day :)
I think there is nothing wrong with your validator pattern regex,
you can remove the pattern's attribute from the input, it is redundant because you are initiating it from inside the ts file: 'myInputField': new FormControl(null, [Validators.pattern('^[0-9]+([,.][0-9])?$')]).
StackBlitz

Primeng KeyFilter not working well

i am using KeyFilter Module of primeng here is my code :
<input type="text" pInputText [(ngModel)]="price.TintCost" [pKeyFilter]="patternDecimal" name="tintCost" required="true" />
here is my typescrip code :
patternDecimal: RegExp = /^[0-9]+(\.[0-9]{1,2})?$/;
and here is version of primeng :|
"primeng": "^5.2.0-rc.1",
i tested in regex then i can type dot(.) but when i apply to KeyFilter, it doesn't allow the dot(.). Someone help me, please
I solved this problem by adding a mask as default
KeyFilter.DEFAULT_MASKS['currencyRegex'] = /^-?(?:0|[1-9]\d{0,2}(?:,?\d{3})*)(?:\.\d+)?$/;
I solved this problem by change the pValidateOnly property to true.
The problem is that the KeyFilter check any press on keyboard and if the complete value is no the correct, then dont permit write, just if you copy and paste the value.
In the documentation say
Instead of blocking a single keypress, the alternative validation mode
which is enabled with pValidateOnly property validates the whole input
with a built-in Angular validator.
https://www.primefaces.org/primeng-6.1.6/#/keyfilter
Example that work for me.
Component.ts
public twoDecimal: RegExp = /^\s*-?(\d+(\.\d{1,2})?|\.\d{1,2})\s*$/
Component.html
<input name="decimalField"
#decimalField="ngModel"
[pKeyFilter]="twoDecimal"
[pValidateOnly]="true"
[(ngModel)]="item.decimalField"
type="text" pInputText>
<div *ngIf="!decimalField.valid" class="alert alert-danger">
<p>Incorrect format.</p>
</div>
The answer of #Norberto Quesada is correct.
Without pValidateOnly the regex will validate on every key stroke.
Let's say you want to enter the value "47.11":
You begin to enter "4" => this would be valid, no input blocked.
Same for "47"
As soon as you enter "47. => validation fails, input blocked.
I was thinking maybe it's possible to enter "4711" first and then the "." in between but for some reason this doesn't seem to work, too... Maybe this is a bug?
Anyways, you can take a look at this stackblitz example for better understanding.
I've also prepared an example of using ValidateOnly and in addition to that restrict the input to only numbers using keyDown event

Input validation with pattern Angular 2

I'm currently writing a simple form in ionic 2 (Angular 2). I was wondering how I'd add a simple regular expression pattern to the validation:
I basically have this:
<form>
<ion-input stacked-label>
<ion-label>{{label.msisdn}}</ion-label>
<input type="text"
[(ngModel)]="msisdn"
ngControl="msisdnForm"
required
maxlength="10"
minlength="10"
pattern="06([0-9]{8})"
#msisdnForm="ngForm"
>
</ion-input>
<button [disabled]="!msisdnForm.valid" block (click)="requestActivationCode()">
{{label.requestActivationCode}}
</button>
</form>
The maxlength, minlength & required are being picked up (the button is disabled if conditions not met). Now I want to limit the input to numeric and prefix it with 06 (Dutch phone number with minimum amount of numbers).
The pattern is however not picked up in the validation. Can I do it this way, or do I need a code approach?
Add the pattern to a variable
var pattern=/06([0-9]{8})/;
and bind the attribute to it
<input type="text"
[(ngModel)]="msisdn"
ngControl="msisdnForm"
required
maxlength="10"
minlength="10"
[pattern]="pattern"
#msisdnForm="ngForm"
>
Seems this PR https://github.com/angular/angular/pull/6623/files needs to land first.
There is still an open issue https://github.com/angular/angular/issues/7595
This prevents pattern being bound to. The pattern needs to be statically added to the DOM (without binding) to work.
I put more details (Angular 2.0.8 - 3 March 2016):
https://github.com/angular/angular/commit/38cb526
Example from repo:
<input [ngControl]="fullName" pattern="[a-zA-Z ]*">
I tested it, and it worked :) - here is my code:
<form (ngSubmit)="onSubmit(room)" #roomForm='ngForm' >
...
<input
id='room-capacity'
type="text"
class="form-control"
[(ngModel)]='room.capacity'
ngControl="capacity"
required
pattern="[0-9]+"
#capacity='ngForm'>
UPDATE September 2017
I just wanna to say that currently when I have more experience, I usally use following 'cheap' approach to data validation:
Validation is ONLY on server side (not in angular at all!) and if something is wrong then server (Restful API) return some error code e.g HTTP 400 and following json object in response body (which in angular I put to err variable ):
this.err = {
"capacity" : "too_small"
"filed_name" : "error_name",
"field2_name" : "other_error_name",
...
}
(if server return validation error in different format then you can usually easily map it to above structure)
In html template i use separate tag (div/span/small etc.)
<input [(ngModel)]='room.capacity' ...>
<small *ngIf="err.capacity" ...>{{ translate(err.capacity) }}</small>
As you see, when there is some error in 'capacity' then tag with error translation (to user language) will be visible. This approach have following advantages:
it is very simple
in angular we not double validation code which is (and must be) in server (in case of regexp validation this can either prevent or complicate ReDoS attacks)
we have full control on way the error will be shown to user (here as egzample in <small> tag)
because in server response we return error_name (instead of direct error message), we can easily change error message (or translate it) by modify only frontend-angular code (or files with translations). So in that case we not need to touch backend/server code.
Of course sometimes (if this is needed - eg. retypePassword field which is never send to server) I make exceptions of above approach and make some validation in angular (but use similar "this.err" mechanism to show errors (so I not use pattern attribute directly in input tag but rather I make regexp validation in some component method after user raise proper event like input-change or save) .

HTML5 number input field step attribute broken in Internet Explorer 10 and Internet Explorer 11

It appears some of my website's users are experiencing issues when attempting to insert values into input fields of type number with the step attribute set.
I am using Django 1.6 to render the forms to HTML.
The number fields map to an underlying DecimalField model field with max_digits=25 and decimal_places=5
This results in the following example html being rendered for the number field:
<input type="number" value="" step="0.00001" name="quantity" id="id_quantity">
The step attribute I know is not yet supported in FireFox but is in Opera, Chrome, Safari and IE10+
Everything works fine in all browsers except IE10 and IE11. In the above example the maximum range that can be entered is -227 to 227 in IE10 and IE11. If I try to enter a lower or greater value (respectively) than this I get a 'You must enter a valid value' error and cannot submit the form.
According to http://www.w3schools.com/tags/att_input_step.asp
The step attribute specifies the legal number intervals for an element.
Example: if step="3", legal numbers could be -3, 0, 3, 6, etc.
So in my user's example they were attempting to enter 20000 as the value which failed in IE10 and IE11. If my calculations are correct 20000 falls correctly into an interval of 0.00001
A solution for me could be to remove the step attribute from all my forms that use a number field, either via the django forms or using javascript, but I think this would be a very messy solution and one that goes against the grain of HTML5.
Has anyone else encountered a similar problem, have I done something wrong or is this a bug in IE10 and IE11?
Any thoughts, comments or answers welcome. In the meantime I will be forced into providing my usual solution to affected users by suggesting they use a browser that works.
You're not alone, IE is pretty buggy on this.
I'm not sure about IE10, I can only test IE11 right now, and it kinda treats number fields as date fields, which it actually shouldn't support at all, still when passing for example 20000 it says "Insert a valid date" (originally "Geben Sie ein gültiges Datum ein").
And indeed, when entering something like 01.01.2000 or 01-01-2000 it passes validation, though even 20000.01.123456789 passes, just like 90000 or 0.foobar, so I guess the validation is just totally messed up.
So for the time being you'll probably have to use some kind of polyfill in case you want to please IE users.
IE10's HTML5 form validation is really buggy in this case, so you might want to consider disabling HTML5 form validation for this form.
You can do this by adding a novalidate attribute to the form tag. For example, you might want to do something like this:
<form method='POST' action='.' novalidate='novalidate'>
<input type="number" value="" step="0.00001" name="quantity" id="id_quantity">
</form>
Setting novalidate will tell the browser to not try to be useful, which should work out your issue. However, please be aware that this will disable the HTML5 validation for the whole form for all browsers. If you need to keep this for some browsers while removing it from IE, you'll have to add the novalidate attribute via Javascript on page load after checking the browser user agent. This user agent can be spoofed however so it's not an ideal solution.
I ran into the same issue and adding step="any" at the field level fixed the issue for me.
It looks like IE10+ need a MIN and MAX value in order to work properly. If you defines these values it will work just fine with the 10000 value:
<input type="number" value="" step="0.00001" min="-100000" max="100000" name="quantity" id="id_quantity" />
Seems that step attributes for numer input just implemented as for Range Input which needs min, max and step values.
If really you are not able to define a min and max value, you must use Javascript to do that.

How do I use a custom Tooltip Text for Invalid Input Pattern instead of "You must use this format: [blank]"

When the input does not match the pattern specified by the pattern attribute, Firefox simply says, "Please match the requested format", which is okay; however, when this validation fails Internet Explorer 10 displays "You must use this format:" in a tooltip with nothing else. This may be simple, but searching has not yielded me a clue as to how to supply text to the tooltip telling it the pattern that should be used.
Example below for a one to four digit number:
<input id="institution_threshold_days" type="text" placeholder="0-9999" pattern="^[0-9]{1,4}$" />
Try using the title attribute to describe what you want it to say:
<input id="institution_threshold_days" type="text" placeholder="0-9999" pattern="^[0-9]{1,4}$" title="Please enter a number less than 10000." />
Should work for all major browsers...
From Microsoft
the content of the title attribute is both shown as tooltip text for
the field and appended to the generic pattern mismatch error message.
From Mozilla
Use the title attribute to describe the pattern to help the
user.
And although I cannot find official documentation, it appears to work in Chrome as well.