UNPKG

@ishitatsuyuki/oruga-next

Version:

UI components for Vue.js and CSS framework agnostic

190 lines (173 loc) 4.36 kB
import { defineComponent } from 'vue' import { getOptions } from './config'; import { getValueByPath } from './helpers' export default defineComponent({ inject: { $field: { from: "$field", default: false } }, emits: ['blur', 'focus'], props: { /** * Makes input full width when inside a grouped or addon field */ expanded: Boolean, /** * Makes the element rounded */ rounded: Boolean, /** * Icon name to be added */ icon: String, /** * Icon pack to use * @values mdi, fa, fas and any other custom icon pack */ iconPack: String, /** Native options to use in HTML5 validation */ autocomplete: String, /** Same as native maxlength, plus character counter */ maxlength: [Number, String], /** Enable html 5 native validation */ useHtml5Validation: { type: Boolean, default: () => { return getValueByPath(getOptions(), "useHtml5Validation", true); }, }, /** Show status icon using field and variant prop */ statusIcon: { type: Boolean, default: () => { return getValueByPath(getOptions(), "statusIcon", true); }, }, /** * The message which is shown when a validation error occurs */ validationMessage: String, }, data() { return { isValid: true, isFocused: false, newIconPack: this.iconPack, }; }, computed: { parentField() { return this.$field; }, /** * Get the type prop from parent if it's a Field. */ statusVariant() { if (!this.parentField) return; if (!this.parentField.newVariant) return; if (typeof this.parentField.newVariant === "string") { return this.parentField.newVariant; } else { for (const key in this.parentField.newVariant) { if (this.parentField.newVariant[key]) { return key; } } } }, /** * Get the message prop from parent if it's a Field. */ statusMessage() { if (!this.parentField) return; return this.parentField.newMessage || this.parentField.hasMessageSlot; }, /** * Icon name based on the variant. */ statusVariantIcon() { const statusVariantIcon = getValueByPath(getOptions(), "statusVariantIcon", { 'success': 'check', 'danger': 'alert-circle', 'info': 'information', 'warning': 'alert' }); return statusVariantIcon[this.statusVariant] || '' } }, methods: { /** * Focus method that work dynamically depending on the component. */ focus() { const el = this.getElement(); if (!el) return; this.$nextTick(() => { if (el) el.focus(); }); }, onBlur(event: Event) { this.isFocused = false; if (this.parentField) { this.parentField.isFocused = false; } this.$emit("blur", event); this.checkHtml5Validity(); }, onFocus(event: Event) { this.isFocused = true; if (this.parentField) { this.parentField.isFocused = true; } this.$emit("focus", event); }, getElement() { let el = this.$refs[this.$elementRef]; while (el && el.$elementRef) { el = el.$refs[el.$elementRef]; } return el; }, setInvalid() { const variant = "danger"; const message = this.validationMessage || this.getElement().validationMessage; this.setValidity(variant, message); }, setValidity(variant, message) { this.$nextTick(() => { if (this.parentField) { // Set type only if not defined if (!this.parentField.variant) { this.parentField.newVariant = variant; } // Set message only if not defined if (!this.parentField.message) { this.parentField.newMessage = message; } } }); }, /** * Check HTML5 validation, set isValid property. * If validation fail, send 'danger' type, * and error message to parent if it's a Field. */ checkHtml5Validity() { if (!this.useHtml5Validation) return; const el = this.getElement(); if (!el) return; if (!el.checkValidity()) { this.setInvalid(); this.isValid = false; } else { this.setValidity(null, null); this.isValid = true; } return this.isValid; }, syncFilled(value) { if (this.parentField) { this.parentField.isFilled = !!value } } } })