niksmr / vue-masked-input

Masked input component for Vue.js
https://niksmr.github.io/vue-masked-input/
MIT License
454 stars 92 forks source link

Change the placeholder char #49

Open oreloffir opened 6 years ago

oreloffir commented 6 years ago

Hi, i try to use this component and it awsome.

now i need to do something in addition and i want to know if there is easy way to do it.

I need to replace the placeholder char with something that is more then 1 char.

the component before focus: image

after focus: image

while texting: image

how can i replace the single placeholderChar '_' with this string dd/mm/yyyy

Aymkdn commented 6 years ago

I'm trying to do the same thing... If you found the solution, please share it !

Aymkdn commented 6 years ago

Here is what I did....

1) We need to remove the check related to the placeholder, and change it to an array. InputMask from inputmask-core :

 function InputMask(options) {
  if (!(this instanceof InputMask)) { return new InputMask(options) }
  options = extend({
    formatCharacters: null,
    pattern: null,
    isRevealingMask: false,
    placeholderChar: DEFAULT_PLACEHOLDER_CHAR,
    selection: {start: 0, end: 0},
    value: ''
  }, options)

  if (options.pattern == null) {
    throw new Error('InputMask: you must provide a pattern.')
  }

  /* remove the validation
  if (typeof options.placeholderChar !== 'string' || options.placeholderChar.length > 1) {
    throw new Error('InputMask: placeholderChar should be a single character or an empty string.')
  }
  */

  // change placeholderChar to be an array:
  this.placeholderChar = (Array.isArray(options.placeholderChar) ? options.placeholderChar : Array(options.pattern.length+1).join(options.placeholderChar))

  this.formatCharacters = mergeFormatCharacters(options.formatCharacters)
  this.setPattern(options.pattern, {
    value: options.value,
    selection: options.selection,
    isRevealingMask: options.isRevealingMask
  })
}

2) Change formatValue from inputmask-core

Pattern.prototype.formatValue = function format(value) {
  var valueBuffer = new Array(this.length)
  var valueIndex = 0
  for (var i = 0, l = this.length; i < l; i++) {
    if (this.isEditableIndex(i)) {
      if (this.isRevealingMask &&
          value.length <= valueIndex &&
          !this.isValidAtIndex(value[valueIndex], i)) {
        break
      }
      valueBuffer[i] = (value.length > valueIndex && this.isValidAtIndex(value[valueIndex], i)
                        ? this.transform(value[valueIndex], i)
                        : this.placeholderChar[i]) // we want to show the rest of the mask
      valueIndex++
    }
    else {
      valueBuffer[i] = this.pattern[i]
      // Also allow the value to contain static values from the pattern by
      // advancing its index.
      if (value.length > valueIndex && value[valueIndex] === this.pattern[i]) {
        valueIndex++
      }
    }
  }

  return valueBuffer;
}

3) Change the different references to placeholderChar because it's now an array:

InputMask.prototype.input in inputmask-core :

InputMask.prototype.input = function input(char) {
  [...]
  var end = this.selection.end - 1
  while (end > inputIndex) {
    if (this.pattern.isEditableIndex(end)) {
      this.value[end] = this.placeholderChar[end] // placeholderChar is now an array
    }
    end--
  }
  [...]
}

Same thing with InputMask.prototype.backspace in inputmask-core

InputMask.prototype.backspace = function backspace() {
  [...]
  if (this.selection.start === this.selection.end) {
    if (this.pattern.isEditableIndex(this.selection.start - 1)) {
      if(this.pattern.isRevealingMask){
        this.value.splice(this.selection.start - 1)
      } else {
        this.value[this.selection.start - 1] = this.placeholderChar[this.selection.start - 1] // placeholderChar is now an array
      }
    }
    this.selection.start--
    this.selection.end--
  }
  else {
    var end = this.selection.end - 1
    while (end >= this.selection.start) {
      if (this.pattern.isEditableIndex(end)) {
        this.value[end] = this.placeholderChar[end] // placeholderChar is now an array
      }
      end--
    }
    this.selection.end = this.selection.start
  }
}

4) Remove the validator in maskedInput.js from this repo :

    placeholderChar: {
      /*type: String,*/
      default: '_',
      /*validator: function validator(value) {
        return !!(value && value.length === 1);
      }*/
    },

5) And finally my component tag looks like that:

<masked-input 
     type="text" 
     mask="1111-11-11" 
     placeholder="YYYY-MM-DD" 
     :placeholder-char="'YYYY-MM-DD'.split('')" 
     v-model="date"></masked-input>
oreloffir commented 6 years ago

here is what i did instead of using this component i used the 'mask' detective and adding this code:

  1. <input type="text" :class="className" v-mask="'##/##/####'" v-model="group.value" :placeholder="placeholder" @focus="setMaskPlaceholder" @blur="setValue" />

  2. data() { return { placeholderOptions: [ 'AGE', 'MM/DD/YYYY' ], selectedPlaceholder: 0 } },

3.computed: { placeholder() { return this.placeholderOptions[this.selectedPlaceholder]; },

  1. methods: { setMaskPlaceholder() { this.selectedPlaceholder = 1; },