I am trying to import a player into my vue.js file. Normally I would use a script file outside of the template, but that does not work.
In an html file what I would do is the following:
<div id="player">
<div id="vplayer"></div>
</div>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/clappr#latest/dist/clappr.min.js"></script>
<script>
var urlsrc = "http://www.streambox.fr/playlists/x36xhzz/x36xhzz.m3u8";
var player = new Clappr.Player({source: urlsrc, parentId: "#vplayer", height: 240, width: 320});
</script>
In vue.js I am trying to do the same thing with the following return code, but it does not work:
<template>
<div id="player">
<div id="vplayer"></div>
</div>
</template>
<script>
export default {
name: 'player',
data () {
return {
script: 'https://cdn.jsdelivr.net/npm/clappr#latest/dist/clappr.min.js',
url: 'http://www.streambox.fr/playlists/x36xhzz/x36xhzz.m3u8',
player: new Clappr.Player({source: this.url, parentId: "#vplayer", height: 240, width: 320})
}
}
}
</script>
I get an error saying that the player is undefined. How can I get normal scripts to run inside of vue.js?
One possible solution is adding external script in created() hooks and use script onload method
<template>
.... your HTML
</template>
<script>
export default {
data: () => ({
url: 'http://www.streambox.fr/playlists/x36xhzz/x36xhzz.m3u8',
player: null
}),
created() {
let clapprScript = document.createElement('script')
clapprScript.setAttribute('src', 'https://cdn.jsdelivr.net/npm/clappr#latest/dist/clappr.min.js')
clapprScript.onload = this.initPlayer;
document.head.appendChild(clapprScript)
},
methods: {
initPlayer() {
this.player = new Clappr.Player({
source: this.url,
parentId: "#vplayer",
height: 240,
width: 320
})
console.log('Player is loaded')
}
}
}
</script>
You should use Mixins. Make your own mixin and then add the methods from imported script inside methods section of mixin.
var mixin = {
methods: {
foo: function () {
console.log('foo')
},
conflicting: function () {
console.log('from mixin')
}
}
}
var vm = new Vue({
mixins: [mixin],
methods: {
bar: function () {
console.log('bar')
},
conflicting: function () {
console.log('from self')
}
}
})
You should be able to do this, after installing Clappr with npm:
<script>
import Clappr from 'clappr';
export default {
created() {
let player = Clappr.Player({...});
}
}
</script>
This way you can initialize your clappr instance in the Vue component just as you would in vanilla html, js scenario.
Related
I have the following component
<template>
<!-- <div :data-test="OUTSIDE_CLICK_DIV">-->
<div
v-click-outside="onClickOutsideHandler"
:data-test="OUTSIDE_CLICK_DIV"
> </div>
...
</template>
<script>
....
export default {
name: "ApplianceForm",
directives: {
clickOutside: vClickOutside.directive,
},
}
</script>
But when I try to create the Test it doesn't recognize the click...
test("calls directive", async () => {
console.log("begin test");
const directiveStub = () => console.log("Directive Stub");
const directiveComponent = mount(ApplianceForm, {
propsData: {
initialData: list[0],
showDiscardModal: showDiscardModal,
},
global: {
directives: {
"click-outside": directiveStub,
},
},
});
const outsideDiv = await directiveComponent.find(`[data-test="${OUTSIDE_CLICK_DIV}"]`);
await outsideDiv.trigger("click");
expect(directiveStub).toHaveBeenCalled();
});
What am I missing how do I override a custom directive using Vue-test-utils?
I've used vue create to setup a new Vue project, and have installed Storybook - all working correctly.
I have then installed storybook-addon-designs and followed the readme on adding to my story, but it gives me the following error in my console: h is not defined.
Here's my files:
stories/2-PageTitle.stories.js:
import { withDesign } from 'storybook-addon-designs'
import {Button} from '../src/components/Button'
export default {
title: 'My stories',
component: Button,
decorators: [withDesign]
}
export const myStory = () => <Button>Hello, World!</Button>
myStory.story = {
name: 'My awesome story',
parameters: {
design: {
type: 'figma',
url: 'https://www.figma.com/file/LKQ4FJ4bTnCSjedbRpk931/Sample-File'
}
}
}
babel.config.js:
module.exports = {
presets: [
'#vue/cli-plugin-babel/preset'
]
}
.storybook/main.js:
module.exports = {
stories: ['../stories/**/*.stories.js'],
addons: ['storybook-addon-designs']
};
src/components/Button.vue:
<template>
<button>
{{ label }}
</button>
</template>
<script>
export default {
name: 'Button',
props: {
label: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
button {
background: red;
}
</style>
Can anyone see what I'm doing wrong here?
Full code here (I'd of done a Sandbox but because it uses Storybook this seems like a better way?): https://github.com/A7DC/storybookvueaddonstest
The author of storybook-addon-designs suggests the following:
You have to replace the export
const myStory = () => <Button>Hello, World!</Button>
You need to change this line (React story) to Vue's one. For example,
export const myStory = () => ({
components: { Button },
template: '<Button>Hello, World!</Button>'
})
Updated answer -
import { withDesign } from "storybook-addon-designs";
import Button from "../src/components/Button";
export default {
title: "My Stories",
decorators: [withDesign],
};
export const myStory = () => ({
components: { Button },
template: "<Button> Hello, World!</Button >",
});
myStory.story = {
name: "My awesome story",
parameters: {
design: {
type: "figma",
url: "https://www.figma.com/file/LKQ4FJ4bTnCSjedbRpk931/Sample-File",
},
},
};
I'm trying to copy a drag and drop task like trello link
Now, how can I call dragdrop.js's function inside MyComponent.vue's method?
Here's what I did...
MyComponent.vue
<template>
....simple html drag and drop structure goes here
</template>
<script>
import dragdrop from './dragdrop.js';
export default {
name: 'my-component',
components: {},
data: () => ({
dragdrop : dragdrop
}),
methods: {
dragStart(e) {
this.dragdrop.dragStart(e);
},
dropIt(e) {
this.dragdrop.dropIt(e);
},
allowDrop(e) {
this.dragdrop.allowDrop(e);
}
}
}
</script>
dragdrop.js
function dragStart(ev) {
....
}
function dropIt(ev) {
....
}
function allowDrop(ev) {
}
I got this error when I start dragging:
VM12491 tickets:36 Uncaught ReferenceError: dragStart is not defined
at HTMLDivElement.ondragstart (VM12491 tickets:36)
VM12492 tickets:36 Uncaught ReferenceError: allowDrop is not defined
at HTMLDivElement.ondragover (VM12491 tickets:36)
Firstly: you don't actually need to put the dragdrop in your data object. Here's a better way:
<script>
import { dropStart, dropIt, allowDrop } from './dragdrop.js'; // ES6 object destructuring
export default {
name: 'my-component',
methods: {
dragStart(e) {
return dragStart(e);
},
dropIt(e) {
return dropIt(e);
},
allowDrop(e) {
return allowDrop(e);
}
}
}
</script>
Answer: My guess is that you should probably return the functions that you want to run. It's hard to tell what the actual problem is with the HTML drag attributes without the actual HTML code though.
Export the function you need to use in the Vue component.
const dragStart = function (ev) {
console.log(ev);
};
export default dragStart;
Now you can import it in Vue like
import dragStart from "./dragdrop";
and can be used inside the component like
created() {
dragStart('test');
}
I want to load the template for a VueJS component dynamically,
I tried this code:
<template>
<div>
<default></default>
<div v-component="{currentView}"></div>
</div>
</template>
<script>
import { Component, Vue, Watch } from "vue-property-decorator";
//import App from './App.vue'
import VueFormWizard from "vue-form-wizard";
#Component({})
export default class detail extends Vue {}
window.addEventListener("load", () => {
window.onload = function() {
//Create the 'default' component
Vue.component("default", {
template: "<div>This should be replaced (and will be in 2 seconds)</div>"
});
//Create the parent ViewModel
var vm = new Vue({
el: "body",
data: {
currentView: "default"
}
});
//Pretend to load the data from the server
//This would actually be $.get("/url", data, function(){...});
window.setTimeout(function() {
//Create the new component using the template we received
Vue.component("BoardFeed", {
template:
'<div>Template returned from server, what I really want</div><br>And directives work too:<div v-repeat="items">{{$value}}</div>',
data: function() {
return {
items: [1, 2, 3]
};
}
});
//And then change the page to that component
vm.currentView = "BoardFeed";
}, 2000);
};
});
</script>
<style>
textarea {
width: 100%;
min-height: 100px;
}
</style>
but I get error:
[Vue warn]: Property or method "currentView" is not defined on the
instance but referenced during render. Make sure that this property is
reactive, either in the data option, or for class-based components, by
initializing the property. See:
https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
How can I fix it?
Currently I'm defining several component template(s) within a single vue component. I've defined some as strings, however it makes it somewhat incomprehensible if it gets more complex. So instead I'm making it return a separate component as a template. However I'm not sure how to pass data to the component.
This is a sample of the current approach for one of my component templates within my vue component. It's returning the template as a string and renders the html.
progessTemplate: function () {
return {
template: ('progessTemplate', {
template: `
<div id="myProgress" class="pbar">
<div id="myBar" :class="barColor" :style="{'width': width}">
<div id="label" class="barlabel" v-html=width ></div>
</div>
</div>`,
data: function () {
return { data: {} };
},
computed: {
width: function () {
if (this.data.SLA <= 20) {
this.data.SLA += 20;
}
return this.data.SLA + '%';
},
barColor: function(){
if(this.data.SLA > 60 && this.data.SLA <= 80){
return 'bar progressWarning';
}else if(this.data.SLA > 80){
return 'bar progressUrgent';
}
}
}
})
}
},
I'd like to avoid this approach and call a separate file instead.
I import the component into my vue file
import QueryDetailTemplate from '../../ej2/queryDetailTemplate';
and within my main vue file I have this function 'QueryDetailTemplate':
export default{
data(){
return{
data: [...],
QueryDetailTemplate: function(){
return {
template: QueryDetailTemplate,
props:{
test: 'Hello World',
},
};
},//end of QueryDetailTemplate
}//end of data
...
}
In my QueryDetailTemplate.vue this is my code:
<template>
<div>
Heyy {{test}} //undefined
</div>
</template>
<script>
export default{
props: ['test'],
created(){
console.log(this.test); //shows undefined
}
}
</script>
It renders the 'Heyy' that's hardcoded but it doesn't get the 'test' prop.
Appreciate any pointers
I'm not quite sure what you're trying to achieve but...you should be specifying the component as a component like so:
export default{
components: {
QueryDetailTemplate
},
data(){
return{
data: [...],
}
}
OR if you want to import it asynchronously:
import Vue from 'vue'
export default {
methods: {
import() {
Vue.component(componentName, () => import(`./${componentName}.vue`));
}
}
}
And then you can render it in main:
<query-detail-template
test='Hello World'>
</query-detail-template>