Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue - Element value was changed outside of mask. #249

Closed
g0ld3neag1e opened this issue Sep 19, 2019 · 8 comments
Closed

Vue - Element value was changed outside of mask. #249

g0ld3neag1e opened this issue Sep 19, 2019 · 8 comments

Comments

@g0ld3neag1e
Copy link

g0ld3neag1e commented Sep 19, 2019

An elements value can easily change outside the mask while using Vue.

I suggest changing the update function in the vue directive from:

        update: function update(el, _ref2) {
            var options = _ref2.value;

            if (options) {
                if (el.maskRef) el.maskRef.updateOptions(options); else initMask(el, options);
            } else {
                destroyMask(el);
            }
        }

to:

        update: function update(el, _ref2) {
            var options = _ref2.value;

            if (options) {
                if (el.maskRef) {
                    //=============//
                    //If the value changes, then Vue will trigger update().
                    //This checks to see if el has focus and, if not, syncs the mask with the new value.
                    if (el !== document.activeElement) {
                        el.maskRef.updateValue();
                        el.maskRef.updateControl();
                    }
                    //=============//
                    el.maskRef.updateOptions(options);
                } else initMask(el, options);
            } else {
                destroyMask(el);
            }
        },

This will prevent the user from having to call updateValue() from outside the mask themselves.

@uNmAnNeR
Copy link
Owner

uNmAnNeR commented Oct 1, 2019

Can you please describe how the value can be changed outside?

@g0ld3neag1e
Copy link
Author

g0ld3neag1e commented Oct 1, 2019

Refer to "How To Use: 2" on this fiddle

https://jsfiddle.net/g0ld3neag1e/ev8k0goy/

This fiddle has my fix applied to it

https://jsfiddle.net/g0ld3neag1e/31kjysu5/

@sem4phor
Copy link

sem4phor commented Oct 7, 2019

@g0ld3neag1e I played around with this fiddle and randomly typing numbers are breaking the Vue value in your fixed fiddle, too. (Tested on macos Latest chrome)

@g0ld3neag1e
Copy link
Author

@sem4phor Yes, the above 'fix,' fixes only a value changed outside of input. Such has an ajax call, or a document.getElement...value = '';

I just reused the same fiddle for both issues. Please refer to only # 2 for this particular issue.

@sem4phor
Copy link

As far as i can see syncing the mask in every directive update hook has no negative impact. (No extra events are fired all values are in sync)

So maybe this could be a solution @uNmAnNeR what do you think?

update (el: any, { value: options }) {
    if (options) {
      if (el.maskRef) {
        el.maskRef.updateOptions(options)
        /**
         *  workaround for following bugs - start
         * - https://github.com/uNmAnNeR/imaskjs/issues/252
         * - https://github.com/uNmAnNeR/imaskjs/issues/249
         */
        el.maskRef.updateValue()
        el.maskRef.updateControl()
        /* workaround - end */
      }
      else initMask(el, options)
    } else {
      destroyMask(el)
    }
  },

@PaulMaly
Copy link
Contributor

PaulMaly commented Dec 2, 2019

@sem4phor The same thing. Seems updateValue completely not working.

@uNmAnNeR
Copy link
Owner

@sem4phor @g0ld3neag1e hello guys! sorry for long delay.
please check https://jsfiddle.net/uNmAjs/r0vdj512/

changed initMask to:

function initMask(el, opts) {
  el.addEventListener('input', e => {
    console.log(e);
    if (e.isTrusted) {
      e.stopPropagation();
      el.maskRef._onInput();
    }
  }, true);
  el.maskRef = new IMask(el, opts).on('accept', function () {
    el.maskRef._unbindEvents();
    fireEvent(el, 'input');
    el.maskRef._bindEvents();
    fireEvent(el, 'accept', el.maskRef);
  }).on('complete', function () {
    fireEvent(el, 'complete', el.maskRef);
  });
}

Seem it's working, and probably it could be done a little bit better: https://github.com/probil/v-mask/blob/master/src/directive.js

But still smells like hack. And also one big disadvantage, that directive can work only with masked values, so there is no way to bind model to unmaskedValue or typedValue, is it?

@uNmAnNeR
Copy link
Owner

found vuejs/vue#3666

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants