RonaldJerez / vue-input-facade

A lightweight and dependency free input masking library created specific for Vue
https://ronaldjerez.github.io/vue-input-facade/latest/
183 stars 27 forks source link

mask is carrying over to new unrelated template and breaking it - Possible facade bug, or possible Vue bug #24

Closed ktiedt closed 4 years ago

ktiedt commented 4 years ago

I do not have a test case yet, I am just digging into this, but it sounds like something others would have ran into so I'm hoping maybe by posting first, I might get some insight before diving into a rabbit hole.

I have a validate-pin component that uses a masked input via vue-input-facade to force only digits up to a set length, once these are verified by the API, the component renders its child template which typically contains another form... in this case, its an email address input, but out of the blue (potentially related to upgrading from 1.2.x beta to 1.3.x... the email input now inherits the mask from the PIN validation template.

Upon inspecting the DOM with dev tools, I can verify that the input is recycled between the 2 forms (which is where this might fall into a Vue bug?)...

I'll be working on a test case for this after I get out of my next meeting (happening now).

The ValidatePin template looks like this:

<template>
    <v-container class="validate-pin">
        <div v-if="!isValid" class="validate-pin">
            <v-form>
                <!-- eslint-disable -->
                <v-text-field
                    class="input-pin"
                    label="Please Enter Pin"
                    type="password"
                    persistent-hint
                    hint="If you did not set up a PIN in the past, then your default PIN is the last 4 digits of your SSN."
                    v-facade="'####'"
                    :error-messages="pinErrors"
                    @input="$v.pin.$touch()"
                    @blur="$v.pin.$touch()"
                    v-model="pin">
                </v-text-field>
                <!-- eslint-enable -->
                <v-btn
                    class="button-submit"
                    color="primary"
                    :loading="loading"
                    :disabled="$v.$invalid"
                    @click="validatePin">
                    Validate Pin
                </v-btn>
            </v-form>
        </div>
        <slot v-if="isValid" name="default">
            You must put guarded content as a child component to overide this.
        </slot>
    </v-container>
</template>

The template in the email view, as that might help for the ValidatePin component in use looks like this:

<ValidatePin :validated="pinValidated">
    <v-container>
        <v-form v-if="!verificationSent">
            <v-text-field
                required
                label="New Email Address"
                v-model="email">
            </v-text-field>
            <v-btn :loading="loading" @click.stop="verifyEmail">Send Verification Link</v-btn>
        </v-form>
        <div v-else>
            <div>
                We emailed a verification link to your new address. This link expires in 1
                hour. Note that your email address will not be changed in our system
                unless the link is clicked.
            </div>
            <v-btn :to="{name: 'profile'}">Back To My Profile</v-btn>
        </div>
    </v-container>
</ValidatePin>
RonaldJerez commented 4 years ago

Hmm this is an interesting one. By the looks of your code the two fields are independent so I don't see why the mask of one would transfer to the other. In my current project where I use input-facade we have forms with multiple fields some with masks, some without and I have yet to run into any of them sharing the mask between fields. I'll be interested to see what you find while debugging.

ktiedt commented 4 years ago

@RonaldJerez yeah I haven't found anything definitive yet, one of my first things after I fix a more critical issue will be to downgrade this package to see if its at all related to a recent update, then go from there. My suspicion is its more vue related, since I inspect the input when its in the ValidatePin state and see its ID, and then when it flips to the email state, the email field gets the same ID again.... However, its only happening in this instance, not in other similar components... It's gonna be a fun one for sure. I will definitely update here what I find out (most likely in the morning) as its approaching 2am here.

ktiedt commented 4 years ago

@RonaldJerez so version wasn't an issue... I've not found a definitive cause of the problem, but I have found a temporary solution that is letting us move forward.

<v-text-field
    required
    v-facade="''"
    label="New Email Address"
    v-model="email">
</v-text-field>

By adding a blank facade to the email input, it removes the PIN masking at least.

[Edit: As it turns out, this is the only difference I was able to spot, our other guarded inputs also declare custom masks. So maybe their is a problem in the directive registration that prevents it from unregistering properly? ]

RonaldJerez commented 4 years ago

That would make sense if you were re-using the same input with the same input object. But the template tree should be creating a new input and input object with its own mask config. The config is saved to the input instance object directly.

ktiedt commented 4 years ago

To be clear, I am not re-using anything.. this recycling is part of the virtual dom optimizations in Vue - it was suggested (from the Vue discord server) that adding a key attribute to the inputs (despite not being part of any type of iterative rendering such as a v-for loop, may fix the problem as well. I'll actually be testing that tomorrow most likely after my current ticket is completed.

RonaldJerez commented 4 years ago

I can try updating the unbind hook to ensure the config for input facade gets deleted from the objects. I’m still confused why the input is been recycled but never the less if it’s happening we can see if that fixes it. I’ll push that update to a beta branch for you to test tomorrow.

RonaldJerez commented 4 years ago

:tada: This issue has been resolved in version 1.3.3-beta.1 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

ktiedt commented 4 years ago

Following up a day late from my original intended test, but here is the results:

RonaldJerez commented 4 years ago

I am closing this for now. I haven't been able to reproduce the actual issue on my side. If anyone else runs into the same issue I will re-open it and look closer into, but for now it seems as you have found a work around.