Draft/Vue

From CODECS Dev

Ideas for features to implement using Vue

Simple ideas:

  • Simple button using cdx styling, with ability to click another input. {{#v-button: text= |href= |class= |targetid= |targetclass= }},

Parser function used twice

Guide to setting a Vue widget

By way of an extension.

File structure

  • extension.json - ResourceLoader modules using packageFiles method
  • PHP files for parser functions
  • modules/ext.codecsvue.widget.js - File where one or multiple 'App's are created and mounted, optionally with values to be passed from data-* set by the parser function
  • modules/components folder containing
    • single-file component(s) with a .vue extension
    • index.js containing the module objects (module.exports) for these components.

extension.json

...

PHP Files

The purpose of the parser function in this example is twofold:

  • Ceates a bit of HTML that uses a class for Vue to mount on. Let's say vue-widget.
  • If the parser function needs to be configurable, make it accept arguments that will get translated to data attributes for the Vue application. The values are used only to set up a basic configuration.
    • An alternative to the use of data attributes is to use ResourceLoader's mw.config, but this will be covered separately.

modules/ext.name.foo.js

This is our startimg point where the Vue application gets initialised and mounted on the HTML element.

( function () {

	const Vue = require( 'vue' );

	// Make it compatible with Vue 2
	Vue.configureCompat( {
		MODE: 3
	} );

	// Many examples out there assume you want to select a single elememt by its id
	// but we need to be able to select multiple elements
	const vueWidgets = document.querySelectorAll(".vue-widget");
	vueWidgets.forEach( function(item) {
		// 'ext.wsvue.components' is the module name we defined in extension.json
		// ButtonLink is a single-component file whose module name is defined in index.js.
		var MyApp = require( 'ext.wsvue.components' ).ButtonLink;

		// Create MyApp with config passed to props, and mount!
		var configProps = item.dataset;
		Vue.createMwApp( MyApp, { configProps } ).mount( item );

	});

}() );

main App.vue

  • The main SFC is conventionally called App, but it is not a requirement.
<template>
 // ...
</template>

<script>
const { defineComponent } = require( 'vue' );
const {
	CdxButton,
	CdxCheckbox,
	CdxIcon,
	// ...
} = require( '@wikimedia/codex' );

module.exports = defineComponent( {
// module.exports = exports = {
	name: 'ButtonLink',
	components: {
        CdxButton,
        CdxTextInput
    },
	props: {
        configProps: {
            type: Array,
            default: []
        }
	},
    data() {
		return {
            config: this.configProps,
            // no need for this.$props.configProps['label']
            label: this.configProps['label'] ?? "...", 
        }
    },
    methods: {
        doSomething() {
            //
        }
    },
    computed: {
        // mySettings() { return this.config.mySettings; }
    },
    mounted() {
       // ... 
    }
});
</script>
  • Although it may not be strictly necessary, MW recommends using defineComponent ("type helper for defining a Vue component with type inference.").