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

Example of how to use vue-the-mask with antd #168

Open
Pacheco95 opened this issue Feb 26, 2021 · 1 comment
Open

Example of how to use vue-the-mask with antd #168

Pacheco95 opened this issue Feb 26, 2021 · 1 comment

Comments

@Pacheco95
Copy link

Pacheco95 commented Feb 26, 2021

I'm adding this example as an issue for those who wants to know how to integrate this awesome lib with ant design for vuejs (antd).

If you go to ant input docs you will find an example of a customized form control. If the link does not scroll to the correct doc section, all you just need to do is to search for "Customized Form Controls".

As you can see, to use antd with 3rd party libraries, there are somre requirements that should be follwed:

Customized or third-party form controls can be used in Form, too. Controls must follow these conventions:

  • It has a controlled property value or other name which is equal to the value of valuePropName-parameters).
  • It has event onChange or an event which name is equal to the value of trigger-parameters).
  • It must be a class component.

Here I'll show you how to create a masked input for brazilian phone input numbers and I'll also use class components and typescript but you can quickly convert the code to "pure" vuejs code. So, let's get our hands dirty!

First of all, you need to create an wrapper component to your custom input like this:

<template>
  <InputMask
    class="ant-input"
    :value="value"
    :mask="['(##) ####-####', '(##) # ####-####']"
    @input="change"
  />
</template>

<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator'
import { Emit, Model } from 'vue-property-decorator'
import { TheMask } from 'vue-the-mask'

@Component({
  components: {
    InputMask: TheMask,
  },
})
export default class BRLPhoneInput extends Vue {
  @Model('change', { type: String })
  readonly value!: string

  @Emit()
  change(value: string) {
    return value
  }
}
</script>

And use it in another component!

<template>
  <div class="container">
    <a-form layout="inline" :form="form" @submit="handleSubmit">
      <a-form-item label="Phone">
        <BRLPhoneInput
          v-decorator="[
            'phone',
            {
              initialValue: value,
              rules: [{ validator: validatePhoneNumber }],
            },
          ]"
        />
      </a-form-item>
      <a-form-item>
        <a-button type="primary" html-type="submit"> Submit </a-button>
      </a-form-item>
    </a-form>
    <div v-show="submittedValue !== null" style="margin-top: 16px">
      <span>Submitted raw phone number:</span>
      <a-tag color="green">{{ submittedValue }}</a-tag>
    </div>
  </div>
</template>

<script lang="ts">
import { Vue, Component } from 'nuxt-property-decorator'
import { WrappedFormUtils } from 'ant-design-vue/types/form/form'
import BRLPhoneInput from '~/components/BRLPhoneInput.vue'

@Component({
  components: {
    BRLPhoneInput,
  },
})
export default class extends Vue {
  form!: WrappedFormUtils
  value = '99999999999'

  submittedValue = null

  beforeCreate() {
    this.form = this.$form.createForm(this, {
      mapPropsToFields: () => ({
        phone: this.$form.createFormField(this.value),
      }),
    })
  }

  handleSubmit(e: Event) {
    e.preventDefault()
    this.form.validateFields((err, values) => {
      if (!err) {
        console.log('Values from form', values)
        this.submittedValue = values.phone
      } else {
        console.error(err)
      }
    })
  }

  validatePhoneNumber(
    _rule: any, // which role is being validated
    value: string | undefined,
    callback: (error?: Error) => void
  ) {
    if (!value) {
      return callback(new Error('Required field'))
    }
    if (value && value.length !== 11) {
      return callback(new Error('BRL phone numbers have 11 digits'))
    }
    callback()
  }
}
</script>

Here, antd will pass initialValue from v-decorator to our BRLPhoneInput component as a prop and everything will work perfectly as expected! See demo below.

gif

Hope it hepls!

@Pacheco95
Copy link
Author

In a more reusable way

// masked-input.vue
<template>
  <InputMask class="ant-input" :value="value" :mask="mask" @input="change" />
</template>

<script lang="ts">
import { Component, Vue } from 'nuxt-property-decorator'
import { Emit, Model, Prop } from 'vue-property-decorator'
import { TheMask } from 'vue-the-mask'

@Component({
  components: {
    InputMask: TheMask,
  },
})
export default class MaskedInput extends Vue {
  @Prop({ type: [String, Array], required: true })
  readonly mask!: string | string[]

  @Model('change', { type: String })
  readonly value!: string

  @Emit()
  change(value: string) {
    return value
  }
}
</script>

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

1 participant