UNPKG

@mutt/widgets-vue

Version:

Mutt forms - VueJS integration

223 lines (191 loc) 5.7 kB
/** * Mutt Forms Vue * Wrapper for Mutt Forms for Vue.js **/ 'use strict' import Mutt from '@mutt/forms' // Widgets import MuttVue from './Form.vue' import MuttWatcher from './Watcher.vue' import MuttText from './widgets/Text.vue' import MuttTel from './widgets/Tel.vue' import MuttTextarea from './widgets/Textarea.vue' import MuttNumber from './widgets/Number.vue' import MuttCheckbox from './widgets/Checkbox.vue' import MuttRadio from './widgets/Radio.vue' import MuttChoice from './widgets/Select.vue' import MuttObject from './widgets/Object.vue' import MuttArray from './widgets/Array.vue' import MuttHidden from './widgets/Hidden.vue' import MuttPassword from './widgets/Password.vue' import MuttLabel from './widgets/helpers/Label.vue' import WidgetMixin from './mixins/WidgetMixin' import ValueSubstituteMixin from './mixins/ValueSubstitute' import { PropsProxy, DataProxy, ComputedProxy, MethodProxy, MuttWidgetProxy, } from './utils' // Proxy used to mock Widget interface to Mutt. // NOTE: This is never used in practice as Vue components // overwrite this value and masqurade as Mutt Widgets /* eslint-disable */ class VueWidget extends Mutt.widgets.Widget { constructor(field, type, id, name, label, attribs = {}, options = {}, initial = null) { super(field, type, id, name, label, attribs, options, initial) } render() { return null } } /* eslint-enable */ export default { install(Vue, options) { // Get the default component list let components = { MuttText, MuttTel, MuttTextarea, MuttNumber, MuttCheckbox, MuttChoice, MuttObject, MuttArray, MuttRadio, MuttHidden, MuttPassword, } // We may in future want to extend the component list if (options && options.hasOwnProperty('plugins')) { // Ensure that plugins allow for overriding core components components = { ...components, ...options.plugins, } } // Setup a new instance of the config, this will later // be used to map field types back to widgets for (let component of Object.values(components)) { let name = component.name let type = name.replace('mutt-', '') if (component.hasOwnProperty('for')) { type = component.for } let VueWidgetProxy = function( field, type, id, name, label, attribs = {}, options = {}, initial = null ) { return new VueWidget( field, type, id, name, label, attribs, options, initial ) } VueWidgetProxy.getWidgetName = () => { return name } Mutt.config.registerWidget(type, VueWidgetProxy) if (component.hasOwnProperty('alternative')) { Mutt.config.registerWidget( component.alternative, VueWidgetProxy ) } } // Register the binding widget Vue.component('mutt-widget', { render(h) { const component = this.resolveWidget() if (component) { return h(component, { on: this.$listeners, props: { field: this.field, readonly: this.readonly, fieldIndex: this.fieldIndex, }, }) } throw new Error( `No Vue component could be found registered for Mutt widget type "${ this.getWidget() }".` ) }, props: [ 'field', 'widget', 'readonly', 'fieldIndex', ], components, methods: { /** * Get the name of the Mutt-internal widget the field should render as. * * @return {string} The name of the Mutt widget to try to use for this field. */ getWidget() { // If a widget is specified directly, we always use this if (this.widget) { return this.widget } // Option overrides take next priority if (this.field.options.hasOwnProperty('widget')) { return this.field.options.widget } // Hidden is a special case, as this can be specified using // a non-widget key if (this.field.options.hasOwnProperty('hidden')) { if (this.field.options.hidden) { return 'hidden' } } // By default we fallback to the field type return this.field.type }, /** * Resolve the Vue component to render based on this field's type and * options. * * @return {string} The kebab-cased Vue component to render (by name). */ resolveWidget() { // As we use a proxy to integrate Mutt Vue widgets into // Vue, we need to 'resolve' this proxy here. Mutt Vue // components are registered globally within Vue, we just // need to resolve the name const widget = Mutt.config.getWidget(this.getWidget()) if (typeof widget === 'function') { if (widget.name === 'VueWidgetProxy') { return widget.getWidgetName() } } return widget }, }, }) /** * Special Mutt Watcher Component */ Vue.component('mutt-watcher', MuttWatcher) /** * Register root vue on global scope to be usable anywhere * outside of mutt-widget */ Vue.component('mutt-vue', MuttVue) Vue.prototype.$mutt = Mutt }, mixin: WidgetMixin, utils: { PropsProxy, DataProxy, ComputedProxy, MethodProxy, MuttWidgetProxy, }, } export { ValueSubstituteMixin, MuttLabel }