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

Cannot change the value programmatically when using vuetify #11

Closed joweste closed 4 years ago

joweste commented 4 years ago

Hi, my backend has a brazilian cep value as "23020180". When my view is appearing on the browser, no mask is applied. The value shows as "23020180" To view the mask formatted value, I have to edit the text-field, deleting or appending some number. Is it the expected behaviour? Is there a way to show the formatted value with mask without edit the field? I'd like to see the text field showing "23020-180". Here is all text-fields as cep and telephones showing without masks when the view is loaded.

image

<v-col cols="12" md="2">
                  <v-text-field
                    label="CEP"
                    v-model="convenio.cep"
                    required
                    append-icon="search"
                    class="purple-input"
                    v-facade="'#####-###'"
                  />
</v-col>
mounted(){
  //from backend, to simulate I have set as bellow
  convenio.cep="23020180"
}
RonaldJerez commented 4 years ago

The expected behavior is to format the initial value, this could be related to #10. I'll install vuetify and check it out.

joweste commented 4 years ago

Only an additional information. If I set the value in created, it seems to work. For sample:

created() {
    this.convenio.cep = "23020180";
  },

But, if set the cep value in mounted(), it doesn't work

joweste commented 4 years ago

Here is more info. See this test: I have this code to use mask with zip code:

<v-col cols="12" md="2">
                  <v-text-field
                    label="CEP"
                    v-model="convenio.cep"
                    required
                    append-icon="search"
                    @click:append="searchCep"
                    class="purple-input"
                    v-mask="'#####-###'"
                  />
</v-col>

data:()=>({
  convenio:{cep:"}
})
;
async created() { //if I use mounted, I have the same problem
    try {
      await this.queryEstados();
    } finally {
      this.convenio.cep = "23020180";
    }
},

methods:{
    async queryEstados() {
      this.loading = true; // Simulated ajax query
      try {
        const resp = await EstadosService.list();
        this.estados = resp.data.data;
      } catch (err) {
        console.log(err);
      } finally {
        this.loading = false;
      }
    },
}

My problem is that the field always shows without a mask, that is "23020180" instead of "23020-180" if I comment "await this.queryEstados ();" the mask works. What would be the problem here.

RonaldJerez commented 4 years ago

My guess is that somehow the v-model reactivity is not properly been sent to the input field when using the directive. Out of curiosity can you try replacing v-text-field with regular input and see if it has the same issue, this would help me narrow down the issue to vuetify integration or a general issue with the library.

joweste commented 4 years ago

Yes, I just tested and with regular input fields it´s working. But with v-text-field is not. But It´s weird. With v-text-field, if just set the value without call await this.queryEstados () it´s work.

RonaldJerez commented 4 years ago

I gave this a try today, It seems that the new value is not been properly sent down to the input when using vuetify, in some instances i'm actually receiving the previous value. This is the same exact issue as #10 because the value is been changed programmatically and vuetify is somehow to letting the value cascade down to the directive. The directive is working fine with manual user input since the right input event is been triggered.

When using created hook, the initial value sent to the directive is the value been set in the created hook. In mounted, the initial value is actually what you have in data(), then the directive receives an update with the new value been set inside mounted.

I'll have to take a look at the vuetify code and see if I can spot anything.

joweste commented 4 years ago

Ok, sorry for not being able to help anymore. I will expect for news.

RonaldJerez commented 4 years ago

:tada: This issue has been resolved in version 1.2.0-beta.4 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

RonaldJerez commented 4 years ago

I looked through the v-text-input code, since vuetify is using a render function they cant bind their component's v-model to the underlying input field's value (a vue limitation). So they have their own internal implementation of v-model, but thats not propertly notifying the directive when it gets updated, or rather its notifying the directive of the update early, before updating the input's value. Thats why sometimes I noticed I was receiving the previous value and not the current one.

To make it work what I can do is when the directive's update hook gets triggered, I can check the vnode value to see if the parent component has its own model, if so use that as the most up to date value instead of the input's value. I'll have to keep an eye on it to make sure it plays nice with other components, but it seem to work for vuetify. Give it a try and let me know if you see any further issues.

joweste commented 4 years ago

Thank you. I see this problem when the field-text is null. In this case CPF is coming from database and it is null. I have to check all values for null an change it to empty string "" to avoid the error. image

RonaldJerez commented 4 years ago

Thanks for checking. I see what the issue is, I’ll try to push an update for it soon.

joweste commented 4 years ago

Hi, I did a fix. Can you evaluate it?

function formatter(value = '', config = {}) {
...
...  tokens = tokens ? Object.assign({}, tokenDefinitions, tokens) : tokenDefinitions; // ensure we have a string

  // oldvalue = value.toString();
//fix 
oldvalue = (value||"").toString();
RonaldJerez commented 4 years ago

yes this will work, it is essentially what I will be doing. I haven't pushed it because I'm just double checking the whole library to ensure there's no other point where null could cause a failure. My mistake was that I seemed to have forgotten that default params only work for undefined and not for null, and i'm using default params in other areas so i'll need to write tests for those as well and fix them accordingly.

RonaldJerez commented 4 years ago

I pushed an update the the @beta release that should fix the null issue.

joweste commented 4 years ago

Hi, Is the @beta release the same? beta 1.2.0-beta4?

RonaldJerez commented 4 years ago

No, @beta points to the latest beta release, which is 1.2.0-beta.5 now. In NPM if you click on versions it will show you the tags and which version they reference.

RonaldJerez commented 4 years ago

:tada: This issue has been resolved in version 1.3.0 :tada:

The release is available on:

Your semantic-release bot :package::rocket: