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

Allow undefined to be passed to v-mask directive #82

Open
Kasheftin opened this issue Aug 13, 2018 · 25 comments
Open

Allow undefined to be passed to v-mask directive #82

Kasheftin opened this issue Aug 13, 2018 · 25 comments

Comments

@Kasheftin
Copy link

I widely use form builder in my app. It receives a config like [{key: name, type: string}, {key: birth, type: date},...] and builds a form. I want to add mask property to text input that related to vue-the-mask directive to be able to specify it in the config like that: {key: ssn, mask: {mask: '###-##-##', tokens: {...}}}.

The issue is that it's optional property, it's defined for ssn but it's not defined for user name field.

Currently I have to add it like that:

<input v-if="option.mask" v-mask="option.mask" ...a lot of other options here...>
<input v-else ...a lot of the same options here...>

That's because v-mask="undefined" throws an error. I would suggest to allow undefined or null option to be passed as v-mask directive argument, and if it's passed just do not apply v-mask directive at all.

@SohrabZ
Copy link

SohrabZ commented Sep 8, 2018

I have the very same issue.

@bart-1990
Copy link

I'm also facing this issue.

@ayrtonvwf
Copy link

Same issue. PR #34 should resolve this issue.

@illjah42
Copy link

Same issue! Very cool and simple directive, but usage inside own components becomes tricky, sometimes a lot of code on input field should be duplicated because we can`t just use something like

v-mask="mask ? mask : false"

Maybe the simpliest way to resolve this is to add a token

'*': /./

then we can use it like

v-mask="mask ? mask : '*'"

@adriandmitroca
Copy link

Same issue.

@tarponjargon
Copy link

same

@samuelcust
Copy link

Same

@lwxbr
Copy link

lwxbr commented Jul 19, 2019

The developer needs to implement this or implement a wild card mask.

The solution I found is:

import {mask} from 'vue-the-mask';

export default {
  directives: {
             mask: {
                ...mask,
                tokens: {
                  ...mask.tokens,
                     '*': /./,
                 }
            },
     
        },
...
}

And in directive v-mask="*", that solves the problem.
Thanks, @illjah42 for the suggestion.

@samuelcust
Copy link

The developer needs to implement this or implement a wild card mask.

The solution I found is:

import {mask} from 'vue-the-mask';

export default {
  directives: {
             mask: {
                ...mask,
                tokens: {
                  ...mask.tokens,
                     '*': /./,
                 }
            },
     
        },
...
}

And in directive v-mask="*", that solves the problem.
Thanks, @illjah42 for the suggestion.

Nice!

@lwxbr
Copy link

lwxbr commented Jul 19, 2019

@samuelcust, sorry for post wrong solution. I thought the developer implemented the directive using directive properties. Like in this doc: https://br.vuejs.org/v2/guide/custom-directive.html. Reading the code. I think the hole is more deep than I thought. Really, there's no way to extend that directive to achieve that. I did add new tokens to the default ones but the problem is the length of the mask, that is hard to change.

@david-mart
Copy link

<template>
  <div class="input-with-label" :class="{ focused }">
    <el-input
      size="mini"
      :placeholder="label"
      v-model="param"
      v-mask="mask || nomask"
      :masked="!!mask"
    />
  </div>
</template>

<script>
export default {
  data() {
    return {
      focused: false,
      nomask: {
        mask: '*'.repeat(255),
        tokens: {
          '*': { pattern: /./ }
        }
      }
    }
  },
  props: ['label', 'value', 'mask'],
}
</script>

Here's my hacky solution to the character length issue

@Alberghini
Copy link

Alberghini commented Nov 30, 2019

Im using v-mask plugin

This solved my problem:
<input v-mask="field.mask ? field.mask : continuousMask(model[field.model])" />

And then I added a method like this:

continuousMask(model){
     let mask = ""
     if(model && model.length){
         for(let i = 0; i < model.length; i++){
             mask += 'X'
         }
     }
     return mask
}

The character "X" means "any symbol", which I think is the same as having no mask

This way the mask will be always the same length as the input value and accept any symbol. This is the way I've found to work like it doesn't have a mask

Anyway, this is a workaround and would be nice if the plugin accepted false to have no mask

Please test before using

@KelvynCarbone
Copy link

The directive has a property masked, example:

v-mask="field.mask" :masked="field.mask ? true : false"

@rsornellas
Copy link

same here

@gvonderau
Copy link

The directive has a property masked, example:

v-mask="field.mask" :masked="field.mask ? true : false"

:masked true / false is how you want the input returned, either in it's Masked or Raw (unmasked) format. In both cases, the mask is still applied to the input field.

@MayaraRMA
Copy link

I'm using this:

directives: {
    mask: (el, binding) => {
      if (!binding.value) return;
      mask(el, binding);
    }
  },

but I don't know if is the best way.

@educkf
Copy link

educkf commented Sep 30, 2020

Awesome solution, @MayaraRMA 👏👏👏

@Igoohd-zz
Copy link

I'm using this:

directives: {
    mask: (el, binding) => {
      if (!binding.value) return;
      mask(el, binding);
    }
  },

but I don't know if is the best way.

Can you show more of the code?

@educkf
Copy link

educkf commented Oct 13, 2020

@igoohd I made like this:

  1. created a helper file with this code:
import { mask } from "vue-the-mask";

export const applyMask = {
	bind(el, binding) {
		if (binding.value && binding.value !== "") {
			mask(el, binding);
		}
	},
	unbind() {},
};
  1. then on the component I needed it, i used it like this:
<template>
     <input v-mask="maskTemplate" />
</template>

<script>
import { applyMask as _mask } from "@/helpers";
export default {
	name: "InputField",
	directives: {
		mask: _mask,
	},
        props: {
                maskTemplate: {
			type: String,
			default: "",
		},
        }
}
</script>

So if maskTemplate prop is empty, it don't apply vue-the-mask, only if maskTemplate prop has any value.

@Igoohd-zz
Copy link

@igoohd I made like this:

  1. created a helper file with this code:
import { mask } from "vue-the-mask";

export const applyMask = {
	bind(el, binding) {
		if (binding.value && binding.value !== "") {
			mask(el, binding);
		}
	},
	unbind() {},
};
  1. then on the component I needed it, i used it like this:
<template>
     <input v-mask="maskTemplate" />
</template>

<script>
import { applyMask as _mask } from "@/helpers";
export default {
	name: "InputField",
	directives: {
		mask: _mask,
	},
        props: {
                maskTemplate: {
			type: String,
			default: "",
		},
        }
}
</script>

So if maskTemplate prop is empty, it don't apply vue-the-mask, only if maskTemplate prop has any value.

<script>
import { mask } from 'vue-the-mask'

export const applyMask = {
    bind (el, binding) {
        if (binding.value && binding.value !== '') {
            mask(el, binding)
        }
    },
    unbind () {}
}
</script>

Your "Helpers" is only with tag script?

@educkf
Copy link

educkf commented Oct 13, 2020

It is a plain .js file, to add simple functions, and not a .vue file.
This is the link to the file:
https://github.com/educkf/senior-frontend-test/blob/master/helpers/index.js

@M-erb
Copy link

M-erb commented Apr 21, 2022

This worked perfect for me with Vue3! Thank you @MayaraRMA for such an elegant solution even 2 years later!

Edit, adding solution here as well:

  directives: {
    mask: (el, binding) => {
      if (!binding.value) return;
      mask(el, binding);
    }
  },

@mod7ex
Copy link

mod7ex commented Aug 24, 2022

I think the right and the safest way is to do it programmatically, in my case i use Maska almost same as what you guys use

so in my custom input in a setup script :

const inputRef = ref(); // element refrence

const maskInput = (v) => {
  if (props.mask) return mask(v, props.mask);
  return v;
};

const handelInput = (e) => {
  if (e.inputType === 'deleteContentBackward') {
    emit('update:modelValue', e.target.value);
  } else {
    const v = maskInput(e.target.value);
    emit('update:modelValue', v);
    inputRef.value.value = v;
  }
};

const vMask = {
  updated(el, binding) {
    console.log(binding.vlaue);
  },
};

@JeffJassky
Copy link

The solutions here don't allow for the dynamic masks.
If I have a mask set, then set it to undefined, it stays masked.

@Hallyson34
Copy link

Hallyson34 commented Mar 28, 2024

My solution for this is: v-mask="option.mask ? option.mask : 'X'.repeat(255)"
X can be changed for another pattern token of v-mask, like these:

Tokens
'#': {pattern: /\d/},
'X': {pattern: /[0-9a-zA-Z]/},
'S': {pattern: /[a-zA-Z]/},
'A': {pattern: /[a-zA-Z]/, transform: v => v.toLocaleUpperCase()},
'a': {pattern: /[a-zA-Z]/, transform: v => v.toLocaleLowerCase()},

Edit: Doesn't allow special characters like space :v

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

No branches or pull requests