How to use annotorious in vue.js template - vue.js

I want to use annotorious (with openseadragon plugin) in a vue.js (vue 3) template.
I've installed annotorious with npm.
This is what i've got so far:
<template>
<div class="flex-grow">
<img ref="tag_img" width="100%" :id="img_id" src='../../assets/images/apple.png'>
</div>
</template>
<script>
import * as Annotorious from '#recogito/annotorious-openseadragon'
import '#recogito/annotorious-openseadragon/dist/annotorious.min.css'
export default {
props: {
img_id: String
},
mounted: function () {
var anno = Annotorious({
image: this.$refs.tag_img
}, {})
anno.setDrawingTool('polygon')
}
}
</script>
I recieve the following error in my browser:
[Vue warn]: Error in mounted hook: "TypeError: Cannot read property 'style' of undefined"
found in
---> <AnnotoriousImage> at src/components/interaction/AnnotoriousImage.vue
<Tagging> at src/components/pages/Tagging.vue
<App> at src/App.vue
<Root>
warn # vue.esm.js?efeb:628
logError # vue.esm.js?efeb:1893
...
vue.esm.js?efeb:1897 TypeError: Cannot read property 'style' of undefined

You are mixing up the standard version of Annotorious (for images) and the OpenSeadragon plugin (for high-res images, displayed in the OpenSeadragon viewer) I believe.
What you are importing is the OpenSeadragon version. But the way you are initializing is the one you'd use for the standard version of Annotorious.
Assuming you want to annotate a normal image: the init is correct. But you'd need to
import * as Annotorious from '#recogito/annotorious'

The answer of Rainer brought me to a working version. It is possible to init it in the mount function of annotorious.
import OpenSeadragon from 'openseadragon'
import * as Annotorious from '#recogito/annotorious-openseadragon'
import '#recogito/annotorious-openseadragon/dist/annotorious.min.css'
export default {
props: {
img_url: String,
default: '../../../assets/images/apple.png'
},
mounted: function () {
const viewer = OpenSeadragon({
id: 'annotorious_container',
minZoomImageRatio: 0,
maxZoomPixelRatio: Infinity,
tileSources: {
type: 'image',
url: require('../../../assets/images/apple.png'),
ajaxWithCredentials: false,
fitBounds: true
}
})
var options = {
disableEditor: true // the default editor is disabled to implement a custom behaviour
}
var anno = Annotorious(viewer, options)
anno.setDrawingTool('polygon')
window.viewer = viewer
window.anno = anno
},
components: {
'Icon': Icon,
'AnnotoriusEditorPopup': AnnotoriusEditorPopup
}
}

Related

Tiptap vue-2 extension throw error on construct

I have basic code from https://tiptap.dev/installation/vue2#3-create-a-new-component, but when component is loaded it throw error vue.esm.js?a026:628 [Vue warn]: Error in nextTick: "InvalidCharacterError: Failed to execute 'createElementNS' on 'Document': The qualified name provided ('[object HTMLDivElement]') contains the invalid name-start character '['."
command executed: npm i #tiptap/vue-2 #tiptap/starter-kit
Element code:
<template>
<editor-content :editor="editor" />
</template>
<script>
import { Editor, EditorContent } from '#tiptap/vue-3';
import StarterKit from '#tiptap/starter-kit';
export default {
components: {
EditorContent,
},
data() {
return {
editor: null,
};
},
mounted() {
this.editor = new Editor({
content: `'<p>Iā€™m running Tiptap with Vue.js. šŸŽ‰</p>'`,
extensions: [StarterKit],
});
},
beforeDestroy() {
this.editor.destroy();
},
};
</script>
you imported '#tiptap/vue-3'; while installed npm i #tiptap/vue-2 #tiptap/starter-kit
Both are not compatible, you need to install the right version your using, there u need to install tiptap/vue3

Why do I receive in TypeError: Object(...) is not a function in Vuejs?

Hi I have installed Vuejs 3 and I am trying to embed a vimeo video with this library: import vueVimeoPlayer from 'vue-vimeo-player'.
I imported this in the main.js like this:
import vueVimeoPlayer from 'vue-vimeo-player'
Vue.use(vueVimeoPlayer)
My view is this one:
<template>
<div id="app">
<vueVimeoPlayer
ref="player"
:video-url="url"
:player-height="500"
:player-width="500"
:autoplay="true"
/>
<div #click="updateUrl()">click me</div>
<div #click="errorUrl()">error pls</div>
</div>
</template>
<script>
import { vueVimeoPlayer } from 'vue-vimeo-player';
export default {
name: 'App',
components: {
vueVimeoPlayer,
},
data () {
return {
url: "https://vimeo.com/605358147/b5c4f01703",
};
},
methods: {
updateUrl() {
this.url = "https://vimeo.com/604413787/dd09a5711";
},
errorUrl() {
this.url = "https://vimeo.com/605266340/a7aa996ffc";
},
},
};
</script>
I receive this huge error:
TypeError: Object(...) is not a function
at Proxy.render (index.es.js?558f:174:1)
at VueComponent.Vue._render (vue.runtime.esm.js?2b0e:3569:1)
at VueComponent.updateComponent (vue.runtime.esm.js?2b0e:4081:1)
at Watcher.get (vue.runtime.esm.js?2b0e:4495:1)
at new Watcher (vue.runtime.esm.js?2b0e:4484:1)
etc
etc
So I wonder what am I doing wrong? Because I saw it working check this url:
https://codesandbox.io/s/m4z5v63jqy
Thanks
Vue.use is not directly available anymore in Vue3, you would have to use createApp().use
That's why you're seeing error. Try like this
Make sure you've install correct version of vue-vimeo-player to support Vue3
import { createApp } from 'vue'
import App from './App.vue'
import vueVimeoPlayer from 'vue-vimeo-player'
const app = createApp(App)
app.use(vueVimeoPlayer).mount("#app");

using vue-chartjs in vue 3 : createElement is not a function

I'm using Vue.js 3 and I can't make a chart with Vue-chartjs because of this error:
Uncaught TypeError: createElement is not a function
at Proxy.render (BaseCharts.js?86fc:8)
at renderComponentRoot (runtime-core.esm-bundler.js?5c40:673)
at componentEffect (runtime-core.esm-bundler.js?5c40:4475)
at reactiveEffect (reactivity.esm-bundler.js?a1e9:42)
at effect (reactivity.esm-bundler.js?a1e9:17)
at setupRenderEffect (runtime-core.esm-bundler.js?5c40:4458)
at mountComponent (runtime-core.esm-bundler.js?5c40:4416)
at processComponent (runtime-core.esm-bundler.js?5c40:4376)
at patch (runtime-core.esm-bundler.js?5c40:3991)
at mountChildren (runtime-core.esm-bundler.js?5c40:4180)
this is App.vue that displays my chart:
<template>
<line-chart />
</template>
<script>
import LineChart from "./components/Chart";
export default {
name: "App",
components: {
LineChart
}
};
</script>
and this is Chart.vue that renders a line chart :
<script>
import { Line } from "vue-chartjs";
export default {
extends: Line,
data: () => ({
chartdata: {
labels: ["January", "February"],
datasets: [
{
label: "Data One",
backgroundColor: "#f87979",
data: [40, 20]
}
]
},
options: {
responsive: true,
maintainAspectRatio: false
}
}),
mounted() {
this.renderChart(this.chartdata, this.options);
}
};
</script>
I have tried this with various forms of data, but apparently, the problem is elsewhere.
Do I have to wait for the vue.js 3 ecosystem to become more complete?
Update 2022
The library supports vue 3 now and you can install as follows :
pnpm add vue-chartjs chart.js
# or
yarn add vue-chartjs chart.js
# or
npm i vue-chartjs chart.js
Old answer
According to this issue this library doesn't support Vue 3 yet, and the origin of this error could explained here :
in vue 2 we do the following to create a render function :
export default {
render(createElement ) { // createElement could be written h
return createElement('div')
}
}
in Vue 3 :
import { h } from 'vue'
export default {
render() {
return h('div')
}
}
which means that createElement is undefined
https://github.com/apertureless/vue-chartjs
Vue Charts does not seem to be ready for vue3
Compatibility
v1 later #legacy
Vue.js 1.x
v2 later
Vue.js 2.x
Discussion about vue3 here: https://github.com/apertureless/vue-chartjs/issues/601
and here: https://github.com/apertureless/vue-chartjs/issues/637

Gridsome Full Calendar build error - no SSR

I'm trying to use the Full Calendar vue component (https://github.com/fullcalendar/fullcalendar-vue) in a Gridsome project like so:
<template>
<div class="tabStaffManage">
<div>
<FullCalendar
ref="staffCalendar"
class="fullCalendar"
defaultView="dayGridMonth"
:events="calendarEvents"
:plugins="calendarPlugins"
:allDaySlot="false"
:header="{
center: 'dayGridMonth, timeGridDay',
right: 'prev, next'
}"
minTime="09:00:00"
:selectable="true"
maxTime="18:30:00"
#eventClick="onEventClick"
#select="onDateSelect"
:showNonCurrentDates="false"
></FullCalendar>
</div>
</div>
</template>
<script>
import { formatDate } from "#fullcalendar/core"
import FullCalendar from "#fullcalendar/vue"
import timeGridPlugin from "#fullcalendar/timegrid"
import dayGridPlugin from "#fullcalendar/daygrid"
import interactionPlugin from "#fullcalendar/interaction"
export default {
components: {
FullCalendar,
},
data() {
return {
calendarPlugins: [dayGridPlugin, timeGridPlugin, interactionPlugin],
}
},
}
</script>
This, however, produces an error on build:
Could not generate HTML for "/staff/dashboard/":
ReferenceError: Element is not defined
at Object.338 (node_modules/#fullcalendar/core/main.esm.js:102:0)
at __webpack_require__ (webpack/bootstrap:25:0)
at Module.552 (assets/js/page--src-pages-staff-dashboard-vue.ea5234e7.js:598:16)
at __webpack_require__ (webpack/bootstrap:25:0)
I understand that Full Calendar does not support SSR. So as per the Gridsome documentation (https://gridsome.org/docs/assets-scripts/#without-ssr-support) I did this to import the component:
I created an alias for it's dependencies in gridsome.config.js like so:
var path = require('path');
api.configureWebpack({
resolve: {
alias: {
"timeGridPlugin": path.resolve('node_modules', '#fullcalendar/timegrid'),
etc....
}
},
})
and required those plugins in the mounted() lifecycle hook:
mounted() {
if (!process.isClient) return
let timeGridPlugin = require('timeGridPlugin')
...
},
components: {
FullCalendar: () =>
import ('#fullcalendar/vue')
.then(m => m.FullCalendar)
.catch(),
}
I then wrapped the FullCalendar component in:
<ClientOnly>
<FullCalendar></FullCalendar>
</ClientOnly>
The extra dependencies required in the mounted() hook are included no problem.
However I now get the following error:
TypeError: Cannot read property '__esModule' of undefined
It seems that components() is failing to import the '#fullcalendar/vue' component.
Am I doing something wrong when importing the '#fullcalendar/vue' component?
Is there another way to include both the '#fullcalendar/vue' component and the plugin dependencies with no SSR?
Requiring the full calendar vue component in main.js by checking the gridsome client API and registering the component globally in vue seems to work and does what I expected:
// Include no SSR
if (process.isClient) {
const FullCalendar = require("#fullcalendar/vue").default
Vue.component("full-calendar", FullCalendar)
}
I also was not pointing to the default object when requiring the other modules in the component:
mounted() {
if (!process.isClient) return
let timeGridPlugin = require('timeGridPlugin').default
...
}

retrieve content from markdown file and convert it to valid HTML code in vuejs

I want to create a documentation page and have some markdown files which represent the main content. I have a navigation sidebar where I can select the specific content.
When clicking on a navigation item I need to read the content from a markdown file. I have a method that returns me the required path but I don't know how to read the file.
Lastly I took marked to render the markdown syntax to HTML code.
I created a small example that shows what is missing
https://codesandbox.io/s/006p3m1p1l
Is there something I can use to read the markdown content?
Use VueResource to retrieve the content from your markdown file.
Import the VueResource, and add it using Vue.use method (main.js):
import Vue from "vue";
import App from "./App";
import VueResource from "vue-resource";
Vue.config.productionTip = false;
Vue.use(VueResource);
new Vue({
el: "#app",
components: { App },
template: "<App/>"
});
Then use this.$http.get() method it within your App.vue file to retrieve the markdown file conent.
You can use markdown parsing library, like Showdown.js, wrapped within a vue.js method, directive or filter.
See: https://github.com/showdownjs/showdown and http://showdownjs.com/
There is also vuejs component wrapper for Showdown:
See: https://github.com/meteorlxy/vue-showdown and https://vue-showdown.js.org/
In your case that should look something like this ( using vue-showdown):
<template>
<div id="app"><VueShowdown :markdown="fileContent"></VueShowdown></div>
</template>
<script>
import VueShowdown from "vue-showdown";
export default {
name: "App",
components: VueShowdown,
data: function() {
return {
fileContent: null,
fileToRender:
"https://gist.githubusercontent.com/rt2zz/e0a1d6ab2682d2c47746950b84c0b6ee/raw/83b8b4814c3417111b9b9bef86a552608506603e/markdown-sample.md",
rawContent: null
};
},
created: function() {
// const fileToRender = `./assets/documentation/general/welcome.md`;
//const rawContent = ""; // Read the file content using fileToRender
// this.fileContent = "### marked(rawContent) should get executed";
this.getContent();
},
methods: {
getContent() {
this.fileContent = "rendering ";
// var self;
this.$http.get(this.fileToRender).then(
response => {
// get body data
this.fileContent = response.body;
},
response => {
// error callback
this.fileContent = "An error ocurred";
}
);
}
}
};
</script>
Check in sandbox: https://codesandbox.io/s/poknq9z6q
If your markdown file load is one time thing, then you could import it data, just like you import the components, js files and libraries:
<template>
<div id="app"><VueShowdown :markdown="fileContent"></VueShowdown></div>
</template>
<script>
import VueShowdown from "vue-showdown";
import MarkDownData from './assets/documentation/general/welcome.md';
export default {
name: "App",
components: VueShowdown,
data: function() {
return {
fileContent: null,
rawContent: null
};
},
created: function() {
// const fileToRender = `./assets/documentation/general/welcome.md`;
//const rawContent = ""; // Read the file content using fileToRender
// this.fileContent = "### marked(rawContent) should get executed";
this.getContent();
},
methods: {
getContent() {
this.fileContent = MarkDownData;
}
}
};
</script>
See: https://codesandbox.io/s/xpmy7pzyqz
You could also do it with a combination of html-loader, markdown-loader & v-html.
First you need to install the loaders:
npm i html-loader markdown-loader
Then declare a computed property that returns an array with the names of the markdown files.
In data - add showContent and set the wanted default value - the init markdown file that gets loaded.
Then in the template - loop through the array and set the wanted markdown file on click.
Then finally, you can load your markdown files with a combination of v-html and template literals.
Example below:
<template>
<div class="home">
<h1>
Markdown files
</h1>
<ul>
<li
v-for="item in docs"
:key="item"
#click="shownContent = item"
>
{{ item }}
</li>
</ul>
<div v-html="require(`!!html-loader!markdown-loader!../assets/docs/${shownContent}.md`)"></div>
</div>
</template>
<script>
export default {
name: 'Home',
data() {
return {
shownContent: 'doc1',
}
},
computed: {
docs() {
return [
'doc1',
'doc2',
'doc3',
]
},
},
}
</script>
This way it's important to note, that the name in the array has to be the same as the markdownfile.
I followed the example as mentioned above. I put the code in a component, not App.vue
https://codesandbox.io/s/xpmy7pzyqz?file=/src/App.vue
I get the following error
[Vue warn]: Invalid prop: type check failed for prop "markdown". Expected String with value "[object Object]", got Object