Vue3 Display PDF Document - javascript

I can grab images and display them in a browser using them as a bytearray without any problem. In Normal C# I was also able to do this with PDFs very easily by inserting this bytearray as an but now in Vue3 I am having troubles doing this same thing I've done in the past. What is a simple way to display a PDF document In browser with Vuejs?
This is how I've done in in the past,
I am open to suggestions and a better way to do this.
This will be hosted and be shown on a big screen TV so the department can view the document and it will flash to other ones as well.
<div v-if="byteArrayPDF" class="content">
<object data="byteArrayPDF" type="application/pdf" style="height:700px;width:1100px;"></object>
</div>
</div>
</template>
<script lang="js">
import Vue from 'vue';
export default Vue.extend({
data() {
return {
loading: false,
byteArrayPDF: null
};
},
created() {
this.fetchByteArray();
},
methods: {
fetchByteArray() {
this.byteArrayPDF = true;
this.loading = null;
fetch('https://localhost:5001/api/Doc/Virtual-Visual-Service-2020.pdf')
.then(response => response.json())
.then(bytespdf => {
this.byteArrayPDF = "data:application/pdf;base64," + bytespdf;
this.loading = false;
return;
})
.catch(console.log("Error PDF View"));
}

From what you said in your question, I think you want to load a pdf file in for example a "vue component". If that is right, you can use a code like the code below:
<template>
<div v-if="byteArrayPDF">
<iframe :src="srcData" width="100%" height="500px">
</iframe>
</div>
<div v-else>
loading...
</div>
</template>
<script>
export default {
name: "CompoPdf",
data() {
return {
srcData: null,
byteArrayPDF: false,
}
},
created() {
this.fetchByteArray();
},
methods: {
fetchByteArray: async function () {
// to see the "loading..." effect, I intentionally add a "setTimeout" code. that loads the pdf after "3s". You can remove it in your real app.
await new Promise(resolve => setTimeout(resolve, 3000));
fetch('https://www.antennahouse.com/hubfs/xsl-fo-sample/pdf/basic-link-1.pdf')
.then(response => {
console.log(response);
// for this case "response.url" is what we need, but if you fetch data for example from a database ... you may need "response.json()" or other codes;
this.srcData = response.url;
this.byteArrayPDF = true;
})
}
}
}
</script>
<style scoped>
</style>
I also suggest that you read more about fetch API and CORS if you are not familiar with that topics, to better manage your request to the url you want.

Related

VUE JS Dynamic background image after axios request

I'm trying to display a background image that it's path needs to be loaded through an API.
The plan is: From a main grid of links, click one and display a background image according to the one clicked.
As of now I am using axios to query my API which sends the data I need. I have the following script part on my component.
<script>
import axios from 'axios'
const lhost = require("#/config/global").host;
let championData;
export default {
name: 'IndividualChampion',
props: {
},
data: () => ({
champions: [],
verPersonagem: mdiMovieOpen,
}),
computed: {
},
created: async function() {
try {
let champion = this.$route.fullPath.split('/')[2];
let response = await axios.get(lhost + "/champion/" + champion + '/full');
championData = response.data
console.log(championData)
let background = '#/assets' + championData['skins']['0']['splash'].replace('.png','.jpg')
}
catch (e) {
return e;
}
},
methods: {
}
}
</script>
And this is my HTML
<template>
<div :style="{ backgroundImage: `url(${require(background)})` }">
</div>
</template>
I have searched but can't seem to find a solution in which the background image is loaded and, when loaded, is presented.
Can someone help?
Judging from your use of '#/assets', you seem to be using webpack with a resolve alias. The expression require(background) is not enough for webpack to determine what files it needs to add to your bundle.
You can help Webpack by specifying the directory that you want to load your file from. All you have to do is take out '#/assets/' from the background variable and use it directly in the require call so that Webpack can see it.
<template>
<div v-if="background" :style="{ backgroundImage: `url(${require('#/assets/' + background)})` }">
</div>
</template>
<script>
import axios from 'axios'
const lhost = require("#/config/global").host;
let championData;
export default {
name: 'IndividualChampion',
props: {
},
data: () => ({
champions: [],
verPersonagem: mdiMovieOpen,
background: ''
}),
computed: {
},
created: async function() {
try {
let champion = this.$route.fullPath.split('/')[2];
let response = await axios.get(lhost + "/champion/" + champion + '/full');
championData = response.data
console.log(championData)
this.background = championData['skins']['0']['loading'].replace('.png','.jpg')
}
catch (e) {
return e;
}
},
methods: {
}
}
</script>
It will bundle every possible file inside the directory, though.
You can read more about it here: https://webpack.js.org/api/module-methods/#dynamic-expressions-in-import

VueJS / v-html shows empty page (Bokeh-html)

I am new to VueJS and I am trying to display a local html-file inside of the Vue Application.
I fetch the html file with axios like following:
<template>
<div>
<h1>bla</h1>
<div v-html="input"></div>
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
input: null,
}
},
created() {
this.loadFile()
},
methods: {
loadFile() {
axios({
method: "get",
url: "../../test.html"
})
.then(result => {
this.input = result.data;
console.log("Data: " + result.data)
})
.catch(error => {
console.error("error getting file: " + error);
});
},
}
}
</script>
We generate the html-Files with Bokeh (interactive Charts). If I open the html Files in the Browser they are shown correctly. These files contain
<script type="text/javascript">
and <script type="application/json">.
I tried this with a simple "Hello World"-html Example and this works fine and gets displayed in Vue. But when I read the actual file, I just get an empty page. The console.log(result.data) shows me the correct and complete html Code but I don't get any errors, so I can't figure out the problem.
Does anyone know, what I have to adjust to make this work?
Thanks !
The reason is the statement this.input = result.data tries to parse result.data as json but it is not.
Send the json from the server and use it in your code properly.
Are you doing this inside of a .vue file or is all of this in a .html file. If in html you need to remember to set the el property on your Vue model to ensure it knows where to render. If this is a .vue there has to be a defined template for the same reason.
Here is a fiddle with an example. Yes the site has issues rendering with correct layout, but it renders. This is an example for <script> tags in your html file or just a raw .js file. Looks like you were making a Vue component (.vue) but the premise is still the same as long as you define the template where the Vue code is to be rendered.
Edit:
What does your vue file look like? This is what I'm expecting.
<template id="foo">
<div v-html="input"></div>
</template>
<script>
export default {
template:'#foo',
data: {
input: null
},
created() {
this.loadFile();
},
methods: {
loadFile() {
let _this = this;
axios({
method: "get",
url: 'https://jsfiddle.net/',
})
.then(result => {
console.log(result);
_this.input = result.data;
console.log("Data: " + result.data)
})
.catch(error => {
console.error("error getting file: " + error);
});
},
}
};
</script>

How do i trigger the event on Play, Pause and end using Plyr.io in vue js

I am playing a video using vimeo in vue js app but i cant able to get the pause event and play event... Below i have given the code which i am using it, but it seems i missed the something or i am not getting the point to add. Video is getting through the API it is playing but i want to get pause event trigger on when video pause.
<template>
<div style="max-height: 560px">
<h1 class="title is-size-3" style="text-align: center;">{{ videoTitle }}</h1>
<vue-plyr ref="plyr">
<div class="plyr__video-embed">
<iframe
v-bind:src="videoUrl"
allowfullscreen
allowtransparency
allow="autoplay"
height="100%"
width="100%"
></iframe>
</div>
</vue-plyr>
<div class="vimeoPlayer"></div>
</div>
</template>
<script>
import { GET_VIDEO } from "../utils/endpoint.js";
const axios = require("axios");
export default {
name: "Vimeo",
data() {
return {
videoUrl: "",
videoTitle: "",
videoVimeoId: ""
};
},
computed: {
player() {
return this.$refs.plyr.player;
}
},
methods: {
onVideoPause: function() {
console.log("Video is Paused");
}
},
mounted() {
this.video_id = this.$route.query.video_id;
axios
.get(api)
.then(response => {
this.videoUrl =
response.data.data.video_url +
"?loop=false&byline=false&portrait=false&title=false&speed=true&transparent=0&gesture=media";
this.videoTitle = response.data.data.title;
this.videoVimeoId = response.data.data.video_url.split("/")[4];
})
.catch(e => {
console.log(e);
});
}
};
</script>
Vimeo has created a nice API wrapper that allows you to do this easily.
install using npm install #vimeo/player --save then import it into your component of choice
import Player from '#vimeo/player
Since you have an already existing iframe player all you need to do is add a ref to it and instantiate the Vimeo player constructor with the DOM element. You can then add event listeners to the instance and call any methods you like when the event is triggered.
Inside your mounted function add the following:
mounted() {
const player = new Player(this.$refs.iframe)
player.on('play', (data) => this.onPlay(data))
player.on('pause', (data) => this.onPause(data))
}
methods: {
onPlay(data) {
console.log("Video is playing", data)
},
onPause(data) {
console.log("Video is paused", data)
}
}
More information can be found at https://github.com/vimeo/player.js
Hope this helps
EDIT
Just realized that you were specifically asking for instructions using plyr.io.
Add these event listeners to the mounted hook.
mounted() {
this.player.on('pause', () => this.onVideoPause())
this.player.on('play', () => this.onVideoPlay())
}
Add "pause" as an emit in :emit attribute in < vue-plyr > to get paused , use "ended" also to get action if player has finished, And assign this as an options inside vue-plyr element,
Ex:
<vue-plyr :emit="['pause','ended']" #pause="ActionController" #ended="endedAction"> <div data-plyr-provider="youtube" data-plyr-embed-id="nM2Da70XfEs"></div> </vue-plyr>
Then, define the ActionController as a function of the methods {},
full example
<script>
export default {
methods: {
ActionController: function(event) {
console.log(event.detail.plyr.currentTime) // to get current time, DON'T FORGET REMOVE IT, just for check 😊
},
endedAction: function(event) {
console.log('end')
}
}
}
</script>
<template>
<vue-plyr :emit="['pause','ended']" #pause="ActionController" #ended="endedAction">
<div data-plyr-provider="youtube" data-plyr-embed-id="nM2Da70XfEs"></div>
</vue-plyr>
</template>
Reference => https://github.com/sampotts/plyr#events

How to add external script to vue component?

I need your help very much...
I have a Vue component and endpoint which gives me a script with a small menu and that script includes some actions.
So, after my script is loaded its actions don't work on a page and I don't know why.
Below the example code:
<template>
<div id="menu"></div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
mounted () {
// here I get a script which contains menu bar with actions
// css and styles
this.$http.get("https://endpointwithscript.com/menu").then(response => {
if (response.status === 200) {
//in that case script doesn't work. Eg click
var div = document.getElementById("menu")
div.innerHTML += response.body;
document.appendChild(div);
}
})
}
}
</script>
If I insert my downloaded script that way :
mounted () {
this.$http.get("https://endpointwithscript.com/menu").then(response => {
if (response.status === 200) {
document.write(response.body);
}
})
}
then script works but another html elements are overridden by that script and not displayed.
How to download script, insert it on a page and keep all functionality ?
Thank you!
You can try adding your external script into Mounted()
mounted() {
let yourScript= document.createElement('script')
yourScript.setAttribute('src', 'https://endpointwithscript.com/menu')
document.head.appendChild(yourScript)
},
<div class="menu"></div>
var div = document.getElementById("menu")
You are grabbing the element by ID, but gave it a class instead. Change the div to be <div id="menu"></div>
You could use v-html to include HTML-Code into a specific tag.
It seems the only way to implement a working script is by defining a new script element.
This worked for me here
https://jsfiddle.net/nh475cq2/
new Vue({
el: "#app",
mounted () {
this.$http.get("https://gist.githubusercontent.com/blurrryy/8f7e9b6a74d1455b23989a7d5b094f3f/raw/921937ea99ff233dfc78add22e18868b32cd11c0/Test").then(res => {
if(res.status === 200) {
let scr = document.createElement('script');
scr.innerHTML = res.body;
document.body.appendChild(scr);
}
})
}
})

Vue.js import images

So I am making an app with a control panel and i want to be able to change a few images inside the app dynamically and my problem is, it just won't work
This is the div I am trying to change
<div class="bg-image bg-parallax overlay" :style="`background-image:url(${bg1url})`"></div>
this is the script part of the Home.vue file
<script>
import axios from 'axios';
export default {
name: 'Home', // this is the name of the component
data () {
return{
page_data: {},
bg1url: null,
};
},
created() {
axios.get("http://localhost:5001/api/v1/pages")
.then((result) => {this.page_data = result.data.page_data});
this.bg1url = require('#/assets/img/' + this.page_data.background1);
alert(page_data.background1);
},
};
</script>
I have tried most of the suggestions on stack overflow but nothing seems to work.
I use the default webpack configurations and generated structure
Note: the parts with axios fetching from the backend work correctly. The only problem is adding the image to the style.
I think could be because you are setting the value for bg1url outsite of promise (calback function of axios), and so this make the code sync and not async
so please try to update, use this instead
created() {
axios.get("http://localhost:5001/api/v1/pages").then(result => {
this.page_data = result.data.page_data
this.bg1url = require('#/assets/img/' + this.page_data.background1);
});
},

Categories

Resources