2

I want to create a keyFilter to verify an IP address using IP-regex as follows:

<input pInputText type="text" [(ngModel)]="value1" [pKeyFilter]= "IPAddressKeyFilter" [pValidateOnly]="true" placeholder="0.0.0.0"/>

The IP verification itself works good but it's still possible to enter any other character except of "[0-9.]"

This is due to pValidateOnly set to true. Otherwise every single key stroke is compared to the IP-regex which will fail (refer to post#1 or post#2).


how to block any input except "[0-9.]"?

Some combination of inputMask and keyFilter/regex would be fine. But the inputMask does not work at all for this use case.

Refer to this example @ stackblitz to get a better understanding of the situation.


UPDATE

I implemented some events (thanks to @Morfioss).

I've updated the stackblitz from above.

Summary:

  • Added Paste-event which was not possible via keyFilter (processes also the IP-regex)
  • Implemented KeyDown-event to check if entered key is "[0-9.]".
  • Fixed prior Paste-event because "CTRL+V" was also blocked via KeyDown-event ("Backspace", "Del" or any navigation with Arrow-Keys as well => bypassed these cases within the event manually...)

So, this is how it's basically implemented so far:

// component.ts
export class AppComponent {
  IPv4AddressKeyFilter: RegExp =
    /(^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)/;

  IPAddressInputOnly: RegExp = new RegExp('[0-9.]');

  valueIPv4: string = '';

  constructor() {}

  ngOnInit(): void {}
  
  OnIPAddressPaste(event: ClipboardEvent) {
    let clipboardData = event.clipboardData;
    let pastedText = clipboardData.getData('text');

    if (this.IPv4AddressKeyFilter.test(pastedText)) {
      this.valueIPv4 = pastedText;
      return true;
    }

    event.preventDefault();
    return false;
  }

  OnIPAddressKeyDown(event: KeyboardEvent) {
    switch (event.key) {
      case 'Backspace':
      case 'Delete':
      case 'ArrowLeft':
      case 'ArrowRight':
      case 'Home':
      case 'End':
        return true;
    }

    if (event.ctrlKey) {
      switch (event.key) {
        case 'c':
        case 'v':
        case 'x':
          return true;
      }
    }

    if (this.IPAddressInputOnly.test(event.key)) {
      return true;
    }
    event.preventDefault();
    return false;
  }
}
<!-- component.html -->
<input
    pInputText
    type="text"
    [(ngModel)]="valueIPv4"
    [pKeyFilter]="IPv4AddressKeyFilter"
    [pValidateOnly]="true"
    placeholder="0.0.0.0"
    (paste)="OnIPAddressPaste($event)"
    (keydown)="OnIPAddressKeyDown($event)"
  />
  

Btw. the KeyPress-event would just work fine unlike the KeyDown... Yet it's deprecated (refer to this post)

I've also tried Input, KeyUp, BeforeInput events which not worked as expected... Not sure what's best-practice to use anyway.

Sample code for these is also provided in the stackblitz above.

I'm not 100% satisfied with this solution but it works out for me so far. Would appreciate any comment, opinion or whatsoever.

flawesome
  • 322
  • 3
  • 9

1 Answers1

1

all you need to do is to add an event in the input :

NumberOnly(e) {
    var regex = new RegExp("[0-9]");
    var str = String.fromCharCode(!e.charCode ? e.which : e.charCode);
    if (regex.test(str)) {
      return true;
    }
    e.preventDefault();
    return false;
  }
  onPaste(e) {
    e.preventDefault();
    return false;
  }
html

<input (input)="NumberOnly($event)"/>

also try adding type="number" in the input in HTML

  • First of all, thank you very much for the reply. It definitely lead me into the right direction. Using type="number" unfortunately does not work for IP address as I also need to enter multiple "." or later for IPv6 ":" and letters from "A" - "F". Anyway, I ended up using the KeyUp event to filter before input. I will update my post and also the example. Maybe someone has better ideas but for now I'm happy with the solution. – flawesome May 12 '22 at 09:59