简体   繁体   中英

Input type=number Safari still allows letters with stepper

I have an input field which only allows number:

 <input class="border" type="number" numeric step="0.1" inputmode="numeric" digitOnly maxlength="6" formControlName="resultInput" pattern="[0-9]+"/>

I set more parameters than needed just to check if it would work with these. Unluckily it didn't. When I am using it on Chrome it works, but when I am using it on Safari it doesn't.

Unfortunately, many browsers will only validate the input for an input with type="number" upon form submission. In such a case, the following prompt will appear (example from Safari):

提示输入数值的 Safari 输入字段。

I've modified your snippet to remove any non-numeric input as it is entered. I have tested that this snippet works on the Chrome, Firefox and Safari.

 <input class="border" type="number" numeric step="0.1" inputmode="numeric" digitOnly maxlength="6" formControlName="resultInput" oninput="this.value = this.value.replace(/[^0-9.]/g, '').replace(/(\..*?)\..*/g, '$1').replace(/^0[^.]/, '0');" />

If you were willing to forgo the stepper, you could avoid having a single non-numerical character remove the entire input:

 <input class="border" type="text" inputmode="numeric" digitOnly maxlength="6" formControlName="resultInput" oninput="this.value = this.value.replace(/[^0-9.]/g, '').replace(/(\..*?)\..*/g, '$1').replace(/^0[^.]/, '0');" />

In these snippets, we use:

oninput="this.value = this.value.replace(/[^0-9.]/g, '').replace(/(\..*?)\..*/g, '$1').replace(/^0[^.]/, '0');" 

to remove all characters that would result in the value in the input not matching a typical numeric form (no leading zeroes, no more than one decimal point).

Be warned: while you can use HTML, CSS and JavaScript to restrict what users enter when using your website normally (known as 'client-side validation'), it is trivial to bypass the restrictions set this way.

If you are sending this data to a server for transformation, you should not trust that this data will only be numeric and of the form you expect. You should consider this type of validation to be purely for convenience's sake rather than providing any guarantee that the server will receive valid data.

The above series of "replace" did not work for me. Since my project is in Angular, I instead created a custom form field validator. That way, an error is presented to the user on invalid input (which prevents form submission):

public static numberInputValidator(min: number, max: number): ValidatorFn {
  return (control: AbstractControl): ValidationErrors | null => {
    if (isUndefinedOrEmpty(control?.value) || control.value <= min) {
      return { numberRequired: true };
    } else if(control.value > max) {
      return { numberTooBig: true };
    }
    return null;
  };
}

The only related attributes on the HTML input field are: type="number" step=".01"

To use it, add the validator to your FormControl in your FormGroup:

myControlName: new FormControl<undefined | number>(undefined, numberInputValidator(0, 100))

And even though the validator takes only number inputs, it will return numberRequired if the form field contains non-numeric characters.

You can then display custom error messages as such this (right after the <input> field) if using Angular Material form fields:

  <mat-error *ngIf="vm.formGroup.get('myControlName')?.errors?.numberRequired">
    <p>Amount must be greater than zero</p>
  </mat-error>
  <mat-error *ngIf="vm.formGroup.get('myControlName')?.errors?.numberTooBig">
    <p>Amount must be less than or equal to 100</p>
  </mat-error>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM