Livewire and Alpine and a masking plugin

Using:

Given this simple blade component:

<div
    x-data=""
    x-init="Inputmask('decimal').mask($refs.input)"
>

    <input
        wire:model.defer="myInput"
        x-ref="input"
        {{ $attributes->merge(['class' => 'text-center flex-1 block w-full py-2 px-4 border border-gr-brown-500 outline-none transition duration-150 ease-in-out sm:leading-5 mask-number-decimal text-center']) }}
    />
</div>

I get an (Inputmask) error at the moment an Livewire update happens in my form. That update does not have to be necessarily on this input.

The exact error is maybe not relevant, as this is something that does not play well between Livewire and AlpineJS, but here is the error I get after a roundtrip:
alpine.js:1907 Uncaught TypeError: Cannot read property 'charAt' of null at Inputmask.onBeforeMask (app.js:4556)

Steps to Reproduce:

  • add an input with the above setup
  • change something else
  • see the error in console

Are you using the latest version of Livewire: yes!

Do you have any screenshots or code examples:
Well, I did go as fancy as below, with the same error happening:

<div
    x-data="{ value: @entangle($attributes->wire('model')) }"
    x-init="Inputmask('decimal').mask($refs.input); "
    x-on:change="value = $event.target.value"
>

    <input
        x-ref="input"
        x-bind:value="value"
        {{ $attributes->whereDoesntStartWith('wire:model')->merge(['class' => 'text-center flex-1 block w-full py-2 px-4 border border-gr-brown-500 outline-none transition duration-150 ease-in-out sm:leading-5 mask-number-decimal text-center']) }}
    />
</div>

Anybody any experiences with this trouble? If you have a better solution for a currency or decimal mask on the frontend I am open to that as wel.

Thanks!

Did you manage to fix this?

Hi, yes I did, I needed to use the onBeforeMask hook to set data correctly like this:

onBeforeMask: function (value, opts) {
     if(null === value){ // fix charAt on null errors
            value= '0.00'
      }
       return value;
}

You could change the line value= '0.00' to any value you have default in your masked input.

If you are interested, here is my component where I use the masking plugin:

<div
    x-data=""
    x-init="
         Inputmask('currency', {
            numericInput: true,
            rightAlign: false,
            autoUnmask: true,
            onBeforeMask: function (value, opts) {
                if(null === value){ // fix charAt on null errors
                    value= '0.00'
                }
                return value;
            }
        }).mask($refs.input);
    "
>

    <input
        x-ref="input"
        x-on:change="$dispatch('input', $refs.input.value)"
        {{ $attributes->merge(['class' => 'text-center flex-1 block w-full py-2 px-4 border border-gr-brown-500 outline-none transition duration-150 ease-in-out sm:leading-5 text-center']) }}
        onfocus="this.select();"
    />
</div>
1 Like