Ionic 7 - Mask on a ion-input

Hello everyone… I need help to implement a mask in an ion-input !
I tried using Maskito as described in the Ionic DOCs, but I was unsuccessful. If anyone can help me with an example that works, I’d be grateful.
I’m using Ionic/Cli 7.1.1, @ionic/angular 7.1.0, @angular-devkit and @angular/cli 16.1.0, @ionic/angular-toolkit 9.0.0

  • NodeJS : v18.16.0
  • Npm : 9.5.1
  • OS : Windows 10

I updated my ionic to 7.1.2 but unfortunately the example ion-input: Custom Input Value Type Styling and CSS Properties doesn’t work. Did you manage to find a solution?

Hi,
We are currently using maskito without an issue. Could you provide some code?

Node 18.16.1
Npm 9.5.1
Mac OS 13.4.1
@ionic/angular 7.1.3
@maskito/angular 1.2.1
@maskito/angular 1.2.1

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import { FormsModule } from '@angular/forms';
import { MaskitoModule } from '@maskito/angular';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, FormsModule, MaskitoModule, IonicModule.forRoot(), AppRoutingModule],
  providers: [{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }],
  bootstrap: [AppComponent]
})
export class AppModule {}

tab1.page.ts

import { Component } from '@angular/core';
import { MaskitoOptions, MaskitoElementPredicateAsync } from '@maskito/core';

@Component({
  selector: 'app-tab1',
  templateUrl: 'tab1.page.html',
  styleUrls: ['tab1.page.scss']
})
export class Tab1Page {

  readonly phoneMask: MaskitoOptions = {
    mask: ['+', '1', ' ', '(', /\d/, /\d/, /\d/, ')', ' ', /\d/, /\d/, /\d/, '-', /\d/, /\d/, /\d/, /\d/],
  };

  readonly cardMask: MaskitoOptions = {
    mask: [
      ...Array(4).fill(/\d/),
      ' ',
      ...Array(4).fill(/\d/),
      ' ',
      ...Array(4).fill(/\d/),
      ' ',
      ...Array(4).fill(/\d/),
      ' ',
      ...Array(3).fill(/\d/),
    ],
  };

  readonly maskPredicate: MaskitoElementPredicateAsync = async (el) => (el as HTMLIonInputElement).getInputElement();

  
  constructor() {}

}

tab1.page.html

<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-title>
      Tab 1
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
  <ion-header collapse="condense">
    <ion-toolbar>
      <ion-title size="large">Tab 1</ion-title>
    </ion-toolbar>
  </ion-header>

  <ion-list>
    <ion-item>
      <ion-input
        label="Card number"
        placeholder="0000 0000 0000 0000"
        [maskito]="cardMask"
        [maskitoElement]="maskPredicate"
      ></ion-input>
    </ion-item>
    <ion-item>
      <ion-input
        label="US phone number"
        placeholder="+1 (xxx) xxx-xxxx"
        [maskito]="phoneMask"
        [maskitoElement]="maskPredicate"
      ></ion-input>
    </ion-item>
  </ion-list>
</ion-content>

Hello everyone! I’m seeking assistance in implementing a mask on an ion-input element. I attempted to use Maskito as instructed in the Ionic documentation, but unfortunately, I wasn’t successful. It would be greatly appreciated if someone could provide me with a working example to help me out. Thank you in advance!

Providing here simple example

import {MaskitoOptions} from '@maskito/core';

export const userNameMask: MaskitoOptions = {
    mask: /^[a-zA-Z\s]{0,40}$/,
   };
export const capitalCaseMask: MaskitoOptions = {
    mask: /^[a-zA-Z\s]+$/,
    postprocessors: [
        ({value, selection}) => ({value: value.toUpperCase(), selection}),
    ],
};

    <ion-item>
            <ion-input
              placeholder="Your Name"
              [maskito]="userNameMask"
              [maskitoElement]="maskPredicate"
            ></ion-input>            
          </ion-item>

But you are looking for step by step details then please check if this could help you
///https://www.youtube.com/watch?v=4moebFaPONw

For me the fix was to import the MaskitoModule into the same module that declares and exports the Component I want to use Maskito in (components.module.ts for me), not into the App Module (app.module.ts). Once I did this Maskito started working.

I’ve built a more complex setup for masking phone numbers considering a chose country flag next to an input:

<ion-input
                label="Phone"
                type="number"
                [maskito]="phoneMaskObs$ | async"
                [maskitoElement]="maskPredicate"
                labelPlacement="floating"
                formControlName="phone"
>
    <ion-select
        aria-label="Country"
        [value]="selectedValue.value"
        interface="alert"
        (ionChange)="setPhoneMask($event)"
    >
        <ion-select-option
            [value]="country.value"
            *ngFor="let country of countryListIcons"
            >{{ country.name }}</ion-select-option
        >
    </ion-select>
</ion-input>

====== TS file ======

private phoneMask$: BehaviorSubject<MaskitoOptions> = new BehaviorSubject(
        this.phoneMaskService.getMaskByCountryCode('RO')
    );
    public readonly phoneMaskObs$ = this.phoneMask$.asObservable();

    protected setPhoneMask(
        event: IonSelectCustomEvent<SelectChangeEventDetail<any>>
    ): void {
        const countryCode = event.detail.value;
        this.phoneMask$.next(
            this.phoneMaskService.getMaskByCountryCode(countryCode)
        );
    }
    protected readonly maskPredicate: MaskitoElementPredicate = async (el) =>
        (el as HTMLIonInputElement).getInputElement();

===== phone mask service ====

public getMaskByCountryCode(countryCode: string): MaskitoOptions {
        if (!countryCode) return this.phoneMaskList[0].mask;
        const mask = this.phoneMaskList.find(
            (m) => m.countryCode === countryCode
        )?.mask;

        if (!mask) return this.phoneMaskList[0].mask;
        return mask;
    }

    public matchAndGetMaskByPhoneNumber(phoneNumber: string): Country | null {
        const defaultCountry = countryListIcons.find((c) => c.value === 'RO');
        if (!phoneNumber) return defaultCountry;

        const countryPhonePrefix = phoneNumber.substring(0, 3);

        const countryCode = this.phoneMaskList.find((m) => {
            const mask = m.mask.mask as string[];
            const maskPrefix = mask.slice(0, 3).join('');
            return maskPrefix === countryPhonePrefix;
        });

        if (!countryCode) return defaultCountry;

        return countryListIcons.find(
            (c) => c.value === countryCode?.countryCode
        );
    }

===== the static lists of country codes and according masks ======

export const countryListIcons: Array<Country> = [
    { name: '🇷🇴', value: 'RO' },
    { name: '🇫🇷', value: 'FR' },
    { name: '🇬🇧', value: 'GB' },
    { name: '🇪🇸', value: 'ES' },
    { name: '🇳🇱', value: 'NL' },
    { name: '🇺🇦', value: 'UA' },
    { name: '🇷🇺', value: 'RU' },
    { name: '🇵🇱', value: 'PL' },
    { name: '🇮🇹', value: 'IT' },
.....

private readonly phoneMaskList: Array<{
        countryCode: string;
        mask: MaskitoOptions;
    }> = [
        {
            countryCode: countryListIcons.find((c) => c.value === 'RO').value,
            mask: {
                mask: [
                    '+',
                    '4',
                    '0',
                    ' ',
                    '(',
                    /\d/,
                    /\d/,
                    /\d/,
                    ')',
                    ' ',
                    /\d/,
                    /\d/,
                    /\d/,
                    '-',
                    /\d/,
                    /\d/,
                    /\d/,
                ],
            },
        },
        {
            countryCode: countryListIcons.find((c) => c.value === 'FR').value,
            mask: {
                mask: [
                    '+',
                    '3',
                    '3',
                    ' ',
                    /\d/,
                    /\d/,
                    ' ',
                    /\d/,
                    /\d/,
                    ' ',
                    /\d/,
                    /\d/,
                    ' ',
                    /\d/,
                    /\d/,
                ],
            },
        },
........