I'm trying to use billboard.js as a simple alternative to d3.js for displaying some line graphs. Unfortunately, I can't seem to get it working in my own repository, nor can I get it working in a vanilla Vue project.
Can anyone tell me if something special is required to get billboard.js up and running in combination with Vue?
My App.vue:
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<div id="chart">
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { bb } from 'billboard.js';
#Component
export default class App extends Vue {
mounted() {
console.log(this);
console.log(bb);
bb.generate({
bindto: '#chart',
data: {
columns: [
['data1', 30, 200, 100, 170, 150, 250],
],
types: {
data1: 'line',
data2: 'area-spline',
},
colors: {
data1: 'red',
data2: 'green',
},
},
});
}
}
</script>
And the error code I get from my devtools:
vue.runtime.esm.js?2b0e:619 [Vue warn]: Error in mounted hook: "TypeError: $$.generatePoint is not a function"
found in
---> <App> at src/App.vue
<Root>
For what it's worth, I am using the following npm versions for this project:
"dependencies": {
"billboard.js": "^2.0.3",
"core-js": "^3.6.5",
"vue": "^2.6.11",
"vue-class-component": "^7.2.3",
"vue-property-decorator": "^8.4.2"
},
I've created a small repository with the minimum code required to reproduce this issue.
Based on the docs, the correct usage for the ESM build is:
// BEFORE:
//import { bb } from 'billboard.js';
// AFTER:
import bb, { line, areaSpline } from 'billboard.js';
export default {
mounted() {
bb.generate({
//...
data: {
types: {
// BEFORE:
//data1: 'line',
//data2: 'area-spline',
// AFTER:
data1: line(),
data2: areaSpline(),
},
}
});
}
}
Also, if you intend to have multiple instances of this chart component on a page, you should pass unique references to the chart's parent element via a ref:
<template>
<!-- BEFORE: -->
<!-- <div id="chart" /> -->
<!-- AFTER: -->
<div ref="chart" />
</template>
<script>
export default {
async mounted() {
// wait til next tick for `ref` to be available below
await this.$nextTick();
bb.generate({
//...
bindto: this.$refs.chart,
});
}
}
</script>
GitHub PR with fixes
Related
I'm having an issue with rendering quasar components in the storybook with Vue and Quasar. I suspect it's not finding the quasar tags in the story. I just followed these steps to set up the project https://quasar.dev/start/vue-cli-plugin and then I ran npx sb init to set up the storybook in my app. After all, compilation works fine but when I view my story on the storybook screen I got the below error that appears. You check the screen here https://prnt.sc/1qd3ywr
I tried all possible solutions but none had worked. Any suggestions would be appreciated.
TypeError: Cannot read property 'screen' of undefined
at setup (http://localhost:6006/vendors~main.iframe.bundle.js:89474:322262)
at callWithErrorHandling (http://localhost:6006/vendors~main.iframe.bundle.js:37183:22)
at setupStatefulComponent (http://localhost:6006/vendors~main.iframe.bundle.js:44151:29)
at setupComponent (http://localhost:6006/vendors~main.iframe.bundle.js:44107:11)
at mountComponent (http://localhost:6006/vendors~main.iframe.bundle.js:42108:13)
at processComponent (http://localhost:6006/vendors~main.iframe.bundle.js:42083:17)
at patch (http://localhost:6006/vendors~main.iframe.bundle.js:41698:21)
at componentEffect (http://localhost:6006/vendors~main.iframe.bundle.js:42220:21)
at reactiveEffect (http://localhost:6006/vendors~main.iframe.bundle.js:36022:24)
at effect (http://localhost:6006/vendors~main.iframe.bundle.js:35997:9)
Here is my story for the quasar component: (quasar.stories.js)
import { QLayout, QPageContainer, QPage, QSelect, QBtn } from 'quasar'
export default {
title: 'Quasar'
}
export const Components = () => ({
title: 'QuasarComponents',
components: { QLayout, QPageContainer, QPage, QSelect, QBtn },
template: `<q-layout>
<q-page-container>
<q-page class="full-height full-width justify-center items-center q-pa-xl">
<div class="col-auto">
<q-input v-model="name" label="Full name" />
<q-select v-model="role" :options="options" label="User Role" />
</div>
</q-page>
</q-page-container>
</q-layout>`,
data () {
return {
name: null,
role: 'User',
options: ['Admin', 'Supervisor', 'User']
}
}
})
main.js
module.exports = {
"stories": [
"../src/**/*.stories.mdx",
"../src/**/*.stories.#(js|jsx|ts|tsx)"
],
"addons": [
"#storybook/addon-links",
"#storybook/addon-essentials"
]
}
preview.js
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
}
This looks like GitHub issue #7263, which is caused by an app extension.
One user discovered a solution:
em-qui is an app-extension that was also declaring quasar as a devDependency (for IDE support...), though on the same version this was somehow causing a confict:
{
"devDependencies": {
"graphql-tag": "^2.10.3",
"quasar": "^1.12.6"
},
}
So I had to separate the two by declaring it in peerDependencies in the app extension:
{
"devDependencies": {
"graphql-tag": "^2.10.3"
},
"peerDependencies": {
"quasar": "^1.12.6"
}
}
and the error went away.
I'm learning Vue and try to build first app with vue-cli.
I have simple local components that works well.
But I have a problem when I want to use external components.
E.g. 'vuetable-2'.
I install it locally via npm using terminal:
npm install --save vue-multiselect
Installation is succesfull and the 'vue-multiselect' folder appears in the 'node_modules' catalogue. Then I add proper references in my Single-File Component 'ms.vue' file:
<template>
<div>
Hello world!
<label class="typo__label">Select with search</label>
<multiselect v-model="value" :options="options" :custom-label="nameWithLang" placeholder="Select one" label="name" track-by="name">
</multiselect>
<pre class="language-json"><code>{{ value }}</code></pre>
</div>
</template>
<script>
import Multiselect from 'vue-multiselect'
export default {
components: {
Multiselect
},
data () {
return {
value: { name: 'Vue.js', language: 'JavaScript' },
options: [
{ name: 'Vue.js', language: 'JavaScript' },
{ name: 'Rails', language: 'Ruby' },
{ name: 'Sinatra', language: 'Ruby' },
{ name: 'Laravel', language: 'PHP' },
{ name: 'Phoenix', language: 'Elixir' }
]
}
},
methods: {
nameWithLang ({ name, language }) {
return `${name} — [${language}]`
}
}
}
</script>
<style>
</style>
Everything compiles well, but when I go to the browser then the page is empty and got the following error in console:
runtime-core.esm-bundler.js?5c40:5435 Uncaught TypeError: selfHook.call is not a function
at callSyncHook (runtime-core.esm-bundler.js?5c40:5435)
at applyOptions (runtime-core.esm-bundler.js?5c40:5227)
at finishComponentSetup (runtime-core.esm-bundler.js?5c40:6006)
at setupStatefulComponent (runtime-core.esm-bundler.js?5c40:5942)
at setupComponent (runtime-core.esm-bundler.js?5c40:5882)
at mountComponent (runtime-core.esm-bundler.js?5c40:4161)
at processComponent (runtime-core.esm-bundler.js?5c40:4137)
at patch (runtime-core.esm-bundler.js?5c40:3784)
at mountChildren (runtime-core.esm-bundler.js?5c40:3950)
at mountElement (runtime-core.esm-bundler.js?5c40:3896)
I've tried with other component and got same error.
My 'App.vue' file:
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<ms></ms>
</div>
</template>
<script>
import ms from './components/ms.vue'
export default {
name: 'App',
components: {
ms
}
}
</script>
<style>
</style>
edit 2020-09-02:
What I see is that the issue appears only in Vue3. When I recreate the whole project in Vue2 everything works well. But still no idea about the core reason of the problem...
import React, { useEffect } from "react";
import Raphael from "raphael/raphael";
import "morris.js/morris.js";
import "morris.js/morris.css";
const Test = () => {
useEffect(() => {
window.Raphael = Raphael;
Morris.Donut({
element: "test",
data: [
{
label: "a",
value: 49,
},
{
label: "b",
value: 51,
},
],
colors: ["#5f76e8", "#01caf1"],
formatter: function (value, data) {
return value + "%";
},
});
}, []);
return <div id="test" />;
};
export default Test;
I want to use morris.js in React.js.
But this code returns an error.
(Line 9:9: 'Morris' is not defined)
However, just before this error phrase appears, the pie chart is briefly visible, but soon the error phrase appears immediately.
How can I use it?
There are a few ways to approach on this one. If the package you mentioned is type of umd or commonjs you can require to use directly:
const yourModule = import('morris.js/morris.js')
Or if you load your package as external such as CDN site, I assume you're now webpack as a bundler, then you just simply configure it in your webpack.config.js:
externals : {
morris: "Morris"
},
And in your html template index.html would look like:
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.min.js"></script>
Then you just simply import to use in your module:
import morris from "morris"
I have a trouble connecting vue2-editor (based on quill) with highlight.js
No matter what I do, I get an error saying:
Syntax module requires highlight.js. Please include the library on the page before Quill.
I'm using nuxt if it changes anything.
I've tried adding this line at the beginning of script tag:
import hljs from'highlightjs';
So it looks like:
<script>
import hljs from'highlightjs';
export default {
middleware: 'hasPermissions',
permissions: [ 'createPosts' ],
...
}
</script>
My plugin where I require vue2-editor:
import Vue from'vue';
import VueEditor from'vue2-editor';
Vue.use(VueEditor);
VueEditor component in my page:
<VueEditor
class="my-4"
v-model="content"
:editor-options="{ modules: { syntax: true } }"
placeholder="Post content" />
EDIT:
I've tried creating my own component and it shows the same error:
<template>
<v-layout
row
wrap>
<v-flex xs12>
<div ref="editor" />
</v-flex>
</v-layout>
</template>
<script>
import Quill from'quill';
export default {
data() {
return {
editor: null
};
},
mounted() {
window.hljs = require('highlight.js');
this.editor = new Quill(this.$refs.editor, {
modules: {
toolbar: [
[{ header: [ 1, 2, 3, 4, false ]}],
[ 'bold', 'italic', 'underline' ]
],
syntax: true
},
theme: 'snow',
formats: [ 'bold', 'underline', 'header', 'italic' ]
});
this.editor.root.innerHTML = this.value;
}
};
</script>
I can successfully print hljs in console in development tools in my browser. What's wrong?
This one should be a better solution, works for me.
https://github.com/surmon-china/vue-quill-editor/issues/39
In fact, this is because quill internal self-closure caused by the
problem, the solution is as follows: modules.syntax from true to
replace a function:
import hljs from 'highlight.js'
import 'highlight.js/styles/monokai-sublime.css'
editorOption: {
modules: {
syntax: {
highlight: text => hljs.highlightAuto(text).value
}
}
}
I struggled with this for a long time too and this answer worked for me!
// highlight.js component
import Vue from 'vue'
import Hljs from 'highlight.js'
import 'highlight.js/styles/googlecode.css'
let Highlight = {}
Highlight.install = function (Vue, options) {
Vue.directive('highlight', function (el) {
let blocks = el.querySelectorAll('pre code');
blocks.forEach((block) => {
Hljs.highlightBlock(block)
})
})
}
export default Highlight
// in main.js
import Highlight from 'path/to/Highlight.js'
Vue.use(Highlight)
I changed import 'highlight.js/styles/googlecode.css'
to import 'highlight.js/styles/monokai-sublime.css' seems to be a more popular and pleasing style.
you could also probably add a
hljs.configure({ // optionally configure hljs
languages: ['javascript', 'ruby', 'python']
});
to select certain languages, but I haven't tried.
Although I still haven't figured out how to change the background color. it shows up white in other places and black background in the quill window.
I have a single file component that uses Chart.Js to render a simple visualization for some hard coded data. I'm calling the Chart.Js library through a CDN in the head section of my index.html.
I'm using the official Webpack template.
For some reason, the chart won't render unless I click on the component inside the Vue Dev Tools extension.
I've tried changing it from computed to created/mounted and that hasn't worked.
Here's my code. Any help getting this to render properly would be much appreciated.
<template lang="html">
<div>
<div class="row">
<div class="col-sm-12 col-md-4">
<canvas id="carbChart"></canvas>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
calories: 3000,
childSex: 'male',
childAge: 'eighteen'
}
},
computed: {
nutrientCharts: function() {
let calories = this.calories;
let carbCtx = document.getElementById('carbChart').getContext('2d');
let carbChart = new Chart(carbCtx, {
type: 'doughnut',
data: {
labels: ['Low', 'Good', 'Too Much'],
datasets: [{
label: 'carbs',
data: [calories * .45, calories * .65, calories * 1],
backgroundColor: ['orange', 'blue', 'red']
}]
}
});
}
}
}
</script>
You have defined the method in a computed property but never used it.
Assuming you want to just get this running, load the chart on mounted:
mounted() {
this.nutrientCharts();
},
methods: {
nutrientCharts: function () {
// your code here
}
}