The target

Make an amount input box

requirements

Only input numbers or decimal points are not allowed to input illegal numbers such as 1.1. Or 1.. 2 The maximum number to enter a two-digit decimal such as 1.22, not 1.222. At this point we are only talking about the system keyboard. Custom keyboards are not recommended because input fields do not get focus. Custom keyboards require a specific input field that does not have a cursorCopy the code

There are no more than three conventional solutions

  • Listen for keyUP/KeyDown/keyPress events and return false or true using event.keycode to determine the value of keycode.

  • Listen for keyup/ keyDown /keypress events to get the current input value from event.target.value and filter for null by regular matching (partial compatibility exists)

  • Listen for input events to get all the current input values from event.target.value, but when the user moves the cursor in the input, it is not known what the current input value is (fully compatible, but not useless).

    So the solution is either number one or number two

Examine the value of input type

  • Type =text pop-up non-numeric keypad experience the worst limited exclusion
  • Type = number The number keyboard is displayed, but event.target.value can only fetch filtered numbers
  • Type = tel Pop-up numeric keypad event.target.value can fetch the correct value, but ios pop-up soft keyboard does not have ‘.’

Let’s start with a little premise, a pro test

  • In Chinese state in keycode is 229

  • The default soft keyboard on Android phones is Chinese, so the code is 229

  • The soft keyboard on ios phones is displayed in English by default, so the code code can be used

  • Android phones cannot listen for keyPress events, but only for keyUp keyDown

  • For ios phones, the soft keyboard displayed in is 1-9 without a ‘.

  • The event.target.value form yields only pure numbers, i.e. 12…. Event.target. value =12


So a solution is in sight


  • Under the androidinput type=telListen for keyUP events, and event.target.value filters input through regex
  • Under the iosinput type=numberFilter input by keypress event event.keycode,

Part of the reference cloud.tencent.com/developer/a…


Here is my simple implementation of the above



<template>
  <x-cell
    :title="label"
    :isBordorBootom = 'isBordorBootom'
    v-clickoutside="doCloseActive"
    :class="[{ 'is-textarea': type === 'textarea', 'is-nolabel': !label }]">
    <div class="mint-field">
      <textarea
        @change="$emit('change', currentValue)"
        ref="textarea"
        class="mint-field-core"
        :placeholder="placeholder"
        v-if="type === 'textarea'"
        :rows="rows"
        :disabled="disabled"
        :readonly="readonly"
        v-model="currentValue">
      </textarea>
      <div class="input-waper" v-else >
        <div class="prefix">
          <slot name="prefix"></slot>
        </div>
        <input
          @change="$emit('change', currentValue)"
          ref="input"
          class="mint-field-core"
          :placeholder="placeholder"
          :maxlength="maxlength"
          :number="type === 'number'"
          :type="type"
          :style="`font-size:${fontSize}; paddingLeft:${paddingLeft}`"
          @focus="focus"
          @blur="$emit('blur')"
          :disabled="disabled"
          :readonly="readonly"
          :value="currentValue"
          @keyup="handleKeyup"
          @keypress="handleKeypress"
          @input="handleInput">
        <div
        @click="handleClear"
        class="mint-field-clear"
        v-if=! "" disableClear"
        v-show="(currentValue ! == '') && type ! == 'textarea' && active"> <! -- <i class="mintui mintui-field-error"></i> -->
          <img src="./[email protected]" class="mint-field-clear-img">
      </div>
         <div class="afterfix">
          <slot name="afterfix"></slot>
        </div>

      </div>

  </div>
  </x-cell>
</template>

<script>
import XCell from '.. /.. /cell/src/cell';
import Clickoutside from '.. /.. /.. /src/utils/clickoutside';
import icon from '.. /.. /icon/src/icon'/** * mt-field * @desc editor, dependent on cell * @module Components /field ** @param {string} [type=text] -field type, Accept text, * @param {string} [label] - label * @param {string} [rows] - Textarea rows * @param {string} [placeholder] - placeholder * @param {string} [disabled] - disabled * @param {string} [readonly] - readonly* @param {string} [state] - Form verification status style, accept error, warning, success * * @example * <mt-field V-model ="value" label="Username"></mt-field>
 * <mt-field v-model="value" label="Password" placeholder="Please enter your password"></mt-field>
 * <mt-field v-model="value" label="Introduce yourself" placeholder="Introduce yourself" type="textarea" rows="4"></mt-field>
 * <mt-field v-model="value" label="Email" placeholder="Success status" state="success"></mt-field>
 */
export default {
  name: 'CommonField'.data() {
    return {
      active: false,
      currentValue: this.value
    };
  },
  directives: {
    Clickoutside
  },

  props: {
    type: {
      type: String,
      default: 'text'
    },
    rows: String,
    label: String,
    placeholder: String,
    readonly: Boolean,
    disabled: Boolean,
    disableClear: Boolean,
    state: {
      type: String,
      default: 'default'
    },
    value: {},
    attr: Object,
    isBordorBootom: {
      type: Boolean,
      default: false
    },
    fontSize: String,
    paddingLeft: String,
    maxlength: Number
  },

  components: { XCell, icon },

  methods: {
    doCloseActive() {
      this.active = false;
    },

    handleInput(evt) {
      this.currentValue = evt.target.value
       console.log('handleInput:', evt)
    },
    handleKeydown(evt) {
      console.log('handleKeydown:', evt)
      if (this.type === 'number') {
        const keyCode = evt.keyCode;
        const inputVal = this.$refs.input.value
        if (this.isNotNumberKeycode(keyCode) || this.isDotStart(keyCode, inputVal)) {
          console.log('organization')
          evt.preventDefault();
          evt.stopPropagation();
          return false;
        }
      }
    },
    handleKeypress(evt) {
      console.log('handleKeypress:', evt)
      if (this.type === 'number') {
        const keyCode = evt.keyCode;
        const inputVal = this.$refs.input.value
        if (this.isNotNumberKeycode(keyCode) || this.isDotStart(keyCode, inputVal)) {
          evt.preventDefault();
          evt.stopPropagation();
          return false;
        }
      }
    },
    isBackspace(keyCode) {
      return keyCode === 8;
    },
    isDot(keyCode) {
      return keyCode === 46 || keyCode === 190;
    },
    isNumber(keyCode) {
      return (keyCode >= 48 && keyCode <= 57);
    },
    isDotStart(keyCode, inputVal) {
      returnthis.isDot(keyCode) && (! inputVal || inputVal ===' ' || /\./.test(inputVal));
    },
    isNotNumberKeycode(keyCode) {
      return! this.isBackspace(keyCode) && ! this.isDot(keyCode) && ! this.isNumber(keyCode); }, handleKeyup(evt) { console.log('handleKeyup:', evt)
      if (this.type === 'number' || this.type === 'tel') {
        let val = evt.target.value
        console.log('Original val:', val)
        val = val.replace(/[^\d.]/g, ' ') // Clear "numbers" and ". Replace (/\.{2,}/g,'. ') // Keep only the first one. Clear redundant two consecutive val = val.replace('. '.'$# $').replace(/\./g, ' ').replace('$# $'.'. ') // Keep only the first one. Remove excess of two consecutive val = val. Replace (/ ^ (\ -) * (\ d +) \. (\ d \ d). * $/,'$1 $2. $3') // Only two decimals can be enteredif(val.indexOf('. ')< 0 && val ! =' '){// If there is no decimal point, Val = parseFloat(val)} console.log(val) // this.currentValue = evt.target.value.replace(/[^\d]/g,' ');
        this.currentValue = val
      }
    },
    handleClear() {
      if (this.disabled || this.readonly) return;
      this.currentValue = ' ';
      this.$emit('handleClear')},focus() {
      this.active = true
      this.$emit('focus')
    }
  }, 
  computed: {
    iconState() {
      if (this.state === 'default') {
        return ' '
      } else if (this.state === 'error') {
        return ' '
      } else if (this.state === 'warning') {
        return ' '
      } else if (this.state === 'success') {
        return ' '
      } else {
        return ' '}},showClear() {
      
    }

  },
  watch: {
    value(val) {
      this.currentValue = val;
    },

    currentValue(val) {
      this.$emit('input', val);
    },

    attr: {
      immediate: true,
      handler(attrs) {
        this.$nextTick(() => {
          const target = [this.$refs.input, this.$refs.textarea];
          target.forEach(el => {
            if(! el || ! attrs)return; Object.keys(attrs).map(name => el.setAttribute(name, attrs[name])); }); }); }}}}; </script> <style lang="scss" scoped>
@import ".. /.. /.. /src/style/var.scss";
input {
  font-family: The1Official_Bold ;
}

.mint-field {
  width: 100%;
}

.mint-field.is-textarea {
    -webkit-box-align: inherit;
        -ms-flex-align: inherit;
            align-items: inherit;
}
.input-waper {
  // border-bottom: 1px solid #EEEEEE;
  // padding: .3rem 0 .3rem 0;

  border-bottom: 1px solid #A1A5B9; padding-right: 5px; display: flex; / / height: 1.1 rem. // padding: .28rem 0rem .27rem 0rem; position: relative; box-sizing: border-box; .mint-field-core { border: 0; padding: 0; display: block; width: 100%; resize: none; box-sizing: border-box; font-size: .46rem; outline:none; color:$color-red;
    padding-right: .5rem;

  }

  .prefix {
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
  .afterfix {
       display: flex;
    flex-direction: column;
    justify-content: flex-end;
    padding-bottom: .4rem;
  }

  ::-webkit-input-placeholder { /* WebKit browsers */
    color: $color-red;
    opacity: .5;
  }
  :-moz-placeholder { /* Mozilla Firefox 4 to 18 */
    color: $color-red;
     opacity: .5;
  }
  ::-moz-placeholder { /* Mozilla Firefox 19+ */
    color: $color-red;
     opacity: .5;
  }
  :-ms-input-placeholder { /* Internet Explorer 10+ */
    color: $color-red; opacity: .5; }} {-webkit-outer-spin-button, input::-webkit-inner-spin-button {-webkit-appearance: none! important; margin: 0; } .mint-field-clear { display: flex; justify-content: center; align-items: flex-end; padding-bottom: .4rem; padding-right: .2rem; } .mint-field-clear-img { width: 14px; height: 14px; } .mint-field-state { color: inherit; margin-left: 20px; } .mint-field-state .mintui { font-size: 20px; } .mint-field-state.is-default { margin-left: 0; } .mint-field-state.is-success { color:#4caf50;
}
.mint-field-state.is-warning {
    color: #ffc107;
}
.mint-field-state.is-error {
    color: #f44336;
}
.mint-field-other {
    top: 0;
    right: 0;
    position: relative;
}
</style>







Copy the code