How to install a Javascript library on VueJS - vue.js

I need to use the Sortable plugin from jQueryUI in my VueJS project, but I don't know how to include libraries on a VueJS 2 project.
This is what I have done so far:
1) Installed jQuery and jQueryUI this way
npm install --save jquery-ui
npm install --save jquery
2) I add these lines to main.js:
window.$ = window.jQuery = require('jquery');
window.$ = $.extend(require('jquery-ui'));
3) I use like this on my component:
<div class="height">
<app-component-component></app-component-component>
</div>
....
export default {
components: {
appComponentComponent: ComponentComponent
},
...
mounted() {
$('.height').sortable();
}
}
But I get this error:
[Vue warn]: Error in mounted hook: "TypeError: $(...).sortable is not a function"
Can you please tell me what I am doing wrong in order to import and use the library?
Thanks in advance

You can put your sortable plugin code in updated() method of vue lifecycle.
updated()
{
this.$nextTick(function () {
jQuery('.height').sortable();
})
}

You have to add this in main.js
global.jQuery = require('jquery');
var $ = global.jQuery;
window.$ = $;
require('jquery-ui');
require('jquery-ui/ui/widgets/sortable');
And you can use it inside mounted as you are.

Related

Using Stencil components with Ionic Vue

In the Stencil docs section on framework integration with Vue it states the following:
In order to use the custom element library within the Vue app, the
application must be modified to define the custom elements and to
inform the Vue compiler which elements to ignore during compilation.
According to the same page this can be achieved by modifying the config of your Vue instance like this:
Vue.config.ignoredElements = [/test-\w*/];
This relates to Vue 2 however. With Vue 3 (which Ionic Vue uses) you have to use isCustomElement as stated here.
Regretably, I can’t for the life of me get Vue and Stencil to play nice. I have tried setting the config like this:
app.config.compilerOptions.isCustomElement = tag => /gc-\w*/.test(tag)
This causes Vue throw the following warning in the console:
[Vue warn]: The `compilerOptions` config option is only respected when using a build of Vue.js that includes the runtime compiler (aka "full build"). Since you are using the runtime-only build, `compilerOptions` must be passed to `#vue/compiler-dom` in the build setup instead.
- For vue-loader: pass it via vue-loader's `compilerOptions` loader option.
- For vue-cli: see https://cli.vuejs.org/guide/webpack.html#modifying-options-of-a-loader
- For vite: pass it via #vitejs/plugin-vue options. See https://github.com/vitejs/vite/tree/main/p
However, I have no idea how to implement any of the above suggestions using Ionic Vue. I have been messing around with chainWebpack in config.vue.js but without success so far.
Any help would be greatly appreciated.
I'm not an expert in Vue but here's how I did it:
Add the following to your ./vue.config.js (or create it if it doesn't exist):
/**
* #type {import('#vue/cli-service').ProjectOptions}
*/
module.exports = {
// ignore Stencil web components
chainWebpack: config => {
config.module
.rule('vue')
.use('vue-loader')
.tap(options => {
options.compilerOptions = {
...options.compilerOptions,
isCustomElement: tag => tag.startsWith('test-')
}
return options
})
},
}
This will instruct Vue to ignore the test-* components. Source: https://v3.vuejs.org/guide/web-components.html#skipping-component-resolution
Next, load the components in ./src/main.ts.
Import the Stencil project:
import { applyPolyfills, defineCustomElements } from 'test-components/loader';
Then replace createApp(App).use(router).mount('#app') with:
const app = createApp(App).use(router);
// Bind the custom elements to the window object
applyPolyfills().then(() => {
defineCustomElements();
});
app.mount('#app')
Source: https://stenciljs.com/docs/vue
Also, if anyone is using vite2+, just edit the vite.config.js accordingly:
import { fileURLToPath, URL } from 'url'
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue({
template: {
compilerOptions: {
isCustomElement: tag => tag.startsWith('test-') // ✅ Here
}
}
}) ],
resolve: {
alias: {
'#': fileURLToPath(new URL('./src', import.meta.url))
}
}
})

Load vue component (truly) dynamically from local file

Is it possible to load a vue component dynamically at runtime (in an electron app to build a plugin system)?
The component is in a specific file
Its path is only known at runtime
The component can either be precompiled (if that is possible, don't know) or is compiled at runtime
A simple example component is listed below
I tried the following approaches, both failing:
Require component
<template>
<component :is="currentComp"></component>
</template>
<script>
...
methods: {
loadComponent(path) {
const dynComp = eval('require(path)'); // use eval to prevent webpackresolving the require
this.currentComp = dynComp;
}
},
...
</script>
The import works, but the line this.currentComp = dynComp; Fails with error message:
Error in data(): "Error: An object could not be cloned."
Using the code presented here, but replace url with a local path
Fails with error message:
Failed to resolve async component: function MyComponent() {
return externalComponent('/path/to/Component.vue');
}
Reason: TypeError: Chaining cycle detected for promise #<Promise>
The used example component is the following:
// Example component
module.exports = {
template: `
<div>
<input v-model="value"/>
<button #click="clear">Clear</button>
<div>{{ value }}</div>
</div>`,
name: 'Example',
data() {
return {
value: '',
};
},
watch: {
value(value) {
console.log('change!');
},
},
methods: {
clear() {
this.value = '';
},
},
};
I found a solution:
Create the vue component as a SFC in a separate file (here src/Component.vue). I didn't try, but probably it works for inline components, too.
Precompile the component using vue-cli-service, which is already a dev dependency, if the project is created using vue-cli (It's nice to use vue-cli here, since the required loaders are already included):
yarn vue-cli-service build --target lib src/Command.vue
The component is compiled to different bundle types in the dist directory. The file [filename].umd.min.js can be imported now.
Import the component dynamically at runtime:
let MyComponent = eval(`require('/absolute/path/to/[filename].umd.min.js')`);
Vue.component('MyComponent', MyComponent);
The require is wrapped inside an eval to prevent webpack of trying to include the import in its bundle and transforming the require into a webpack__require.
(Optional) If the SFC component contains a <style>...</style> tag, the resulting css is compiled to a separate file. The css can be inlined in the js file by adding the following lines to the vue.config.js in the components project root:
module.exports = {
...
css: {
extract: false,
},
};
You can probably look into async loading:
https://v2.vuejs.org/v2/guide/components-dynamic-async.html#Async-Components
and see this for a webpack lazy load example:
https://vuedose.tips/dynamic-imports-in-vue-js-for-better-performance/#the-meat%3A
These are just some things I would research for your requirements.

getting error when trying to upgrade to vuetify 2.0

Ok so I am trying for the second time to migrate thus far it has been a complete failure it seems that vuetify is not detected, unfortunately I cannot share my full repo since it is work related, but will describe steps and share relevant code.
Project was created with vue-cli 3.3.0 with a vue.config.js file for environment variables.
1) npm uninstall vuetify
2)vue add vuetify
3)npm run serve
my site does not load and I get this error (adding code):
//vue.config.js
module.exports = {
chainWebpack: (config) => {
config.plugin('define')
.tap(([options, ...args]) => {
let env = options['process.env'].VUE_APP_ENV.replace(/"/g,'');
let envMdl = require('./build/' + env.toString() + '.js');
// replace all current by VUE concrente ones to be passed to the app
const processEnv = Object.assign({}, options['process.env'])
Object.keys(envMdl).forEach(function (k) {
processEnv['VUE_APP_' + k] = envMdl[k];
});
const ret = Object.assign({}, options, {'process.env': processEnv});
return [
ret,
...args
]
})
}
}
//vuetify.js
import Vue from 'vue'
import Vuetify from 'vuetify/lib'
Vue.use(Vuetify)
export default new Vuetify({
icons: {
iconfont: 'mdiSvg',
},
})
//main.js
import vuetify from './plugins/vuetify'
...
new Vue({
vuetify,
router,
store,
i18n,
render: h => h(App),
...
Error message (and screenshot): Uncaught TypeError: _lib.default is not a constructor
at eval (vuetify.js?402c:6)
The main problem is that Vuetify v1 works under the Stylus preprocessor, and in v2 it works under the SASS preprocessor, and I personally do not recommend migrating to v2 if it is too advanced and even worse if it has custom Vuetify components.

gojs with vuejs and webpack

I'm trying to set up a simple gojs diagram into vuejs + webpack.
I installed gojs with npm and imported it on my project in the main.js file: import go from 'gojs'
Now my problem is how to make things work in the component implementation, that's the code of the component Diagram.vue:
<template>
<div id="myDiagramDiv" style="width:300px; height:300px;"></div>
</template>
<script>
export default {
name: 'Diagram',
data: function () {
return {
nodeDataArray: [
{key:1, text:"Alpha"},
{key:2, text:"Beta"}
],
linkDataArray: [
{from:1, to:2}
]
}
},
methods: {
getUnits: function(){
var $ = go.GraphObject.make;
myDiagram = $(go.Diagram, "myDiagramDiv");
myDiagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);
}
},
mounted: function(){
this.getUnits();
}
}
</script>
it compiles without error but I can only see a white empty box...
You haven't initialized the Diagram yet. That is typically done by calling go.GraphObject.make(go.Diagram, theHTMLDivElement, { . . . options . . .})
There is a complete but simple example of using GoJS in a Vue.js framework at https://gojs.net/latest/samples/vue.html.
ow my problem is how to make things work in the component implementation
There is an official (made by the GoJS team) VueJS + Webpack + GoJS project in the gojs-projects github, that you can use as an example: https://github.com/NorthwoodsSoftware/GoJS-projects

VueJS use NPM Component in Browser using Browserify

I have a custom component in my page, defined as:
Vue.component('payment-page', {
template: '#payment-template',
data: function () {
return {
...
}
},
components: {
DatePicker
},
});
Now, in this component, I need to use a datepicker/daterange picker, of which I found this to be most helpful. It can be installed from NPM using npm install vue2-datepicker --save. I am using browserify so as to be able to use the datepicker in the browser, inside my component above.
For browserify, inside my main.js file I have this:
let DatePicker = require('vue2-datepicker');
then I use the command browserify main.js -o bundle.js to create my bundle.js file which I then import in my HTML file.
Problem is I always get the error Uncaught ReferenceError: DatePicker is not defined. Anything I'm doing wrong?