How should I bind to an iframe src with something received back via the YouTube data api?
Can I set a string inside :src and concatenate onto the end of it?
/embed/'this.param.videoId'
The response returns an Id {{ video.snippet.resourceId.videoId }}, but the url contains other parts src=“https://www.youtube.com/embed/xxx”
Any help greatly appreciated!
Thanks
This worked:
:src="ytEmbedUrl + video.snippet.resourceId.videoId"
iframe resolving only when there's a videoId:
<iframe v-if="videoId" :src="mySrc"></iframe>
computed property:
computed: {
mySrc: {
get: function() {
//concat using template literal
return `https://www.youtube.com/embed/${this.videoId}`
}
}
}
data property:
{
videoId: false
}
Your method to assign to it:
methods: {
getMyVideo() {
video = // get my video code
this.videoId = video.snippet.resourceId.videoId
}
}
Or just inline it if you're super lazy:
<iframe src="`https://www.youtube.com/embed/${videoId}`"></iframe>
Here is what is working for me with Bootstrap V5 css
<template>
<section class="video-player-container">
<div class="video-player-row">
<div
class="video-player ratio"
:class="`ratio-${group.videoAspectRatio}`"
>
<iframe
loading="lazy"
:src="`https://www.youtube.com/embed/${getIdFromURL(group.videoEmbedLink)}?rel=0`"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
/>
</div>
</div>
</section>
</template>
<script>
export default {
name: 'VideoPlayer',
props: {
group: {
type: Object,
required: true
}
},
methods: {
getIdFromURL (url) {
const youtubeRegexp = /https?:\/\/(?:[0-9A-Z-]+\.)?(?:youtu\.be\/|youtube(?:-nocookie)?\.com\S*[^\w\s-])([\w-]{11})(?=[^\w-]|$)(?![?=&+%\w.-]*(?:['"][^<>]*>|<\/a>))[?=&+%\w.-]*/ig
let id = url.replace(youtubeRegexp, '$1')
if (id.includes(';')) {
const pieces = id.split(';')
if (pieces[1].includes('%')) {
const uriComponent = decodeURIComponent(pieces[1])
id = `http://youtube.com${uriComponent}`.replace(youtubeRegexp, '$1')
} else {
id = pieces[0]
}
} else if (id.includes('#')) {
id = id.split('#')[0]
}
return id
}
}
}
</script>
<style scoped lang="scss">
.video-player {
&-container {
#include make-container();
#include default-max-widths();
}
&-row {
#include make-row();
}
}
</style>
Related
Basically, I want a dynamic link on my a href based on the code. Where I want my link to be to example2.com when the website using my NuxtJS code is example1.com.. However, it will always get linked to / instead of example2.com.. It is really weird as it can clearly be seen in Vue Inspection Tool and in {{ backHref }} that it is already returning example2.com.. However it does not reflect in :href
/* eslint-disable vue/no-v-html */
<template>
<div class="h-100 bg-ededed">
<a :href="backHref">{{ backHref }}</a>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
meta: { noFooter: true },
computed: {
...mapState({
chatRooms: (state) => state.chat.chatRooms
}),
backHref() {
let link
if (this.chatRooms.length === 1) {
console.log(`this.isExample: ${this.isExample}`)
if (this.isExample) {
console.log('went here 1')
link = 'https://example2.com'
} else {
console.log('went here 2')
link = '/'
}
} else {
link = '/chat/'
}
console.log(
`this.addChannelCodeLink(link): ${this.addChannelCodeLink(link)}`
)
return this.addChannelCodeLink(link)
},
getDomain() {
let host
if (process.client && window) {
host = window.location.host
}
return host
},
isExample() {
return this.getDomain ? this.getDomain.includes('example1.com') : false
}
},
methods: {
addChannelCodeLink(link) {
if (this.$route.query.r) {
link += `?r=${this.$route.query.r}`
}
return link
}
}
}
</script>
<style lang="scss" scoped></style>
Console.log will be something like this:
- While in SSR
this.isExample: false
went here 2
this.addChannelCodeLink(link): /
- In Client
this.isExample: true
went here 1
this.addChannelCodeLink(link): http://example2.com
I am using YouTube iFrame to embed YouTube player into my NuxtJS application. videoId is passed as property to the component. And then URL is constructed and returned as data property to src attribute of iFrame.
YoutubePlayer.vue
props: {
videoId: {
type: String,
required: true
}
},
data() {
return {
videoUrl:
"https://www.youtube.com/embed/" +
this.videoId+
"?autoplay=1&origin=http://example.com"
};
}
<template>
<div class="iframeContainer">
<iframe
id="ytplayer"
width="640"
height="360"
:src="videoUrl"
></iframe>
</div>
</template>
But this is not working. What am I doing wrong?
UPDATE: No error in the console and nothing on the screen.
Can you try to check this?
props: {
videoId: {
type: String,
required: true
}
},
data() {
return {
videoUrl: '',
};
},
watch: {
videoId: function(newVal) {
this.videoUrl = "https://www.youtube.com/embed/" +
newVal +
"?autoplay=1&origin=http://example.com"
}
}
Vue version : 3.1.1
Hey guys,
I'm working with dynamic Creation Component, which means a user can add whatever of component he wants.I create it base on this documentation dynamic component creation.
And I use this component vue image uploader.
I need to send an index when the user wants to upload the image, like this :
<div v-for="(line, index) in lines" v-bind:key="index">
{{index}}//if i log the index its 0,1,2,3 and its ok
...
<image-uploader
:preview="true"
:class-name="['fileinput', { 'fileinput--loaded': line.hasImage }]"
:capture="false"
:debug="0"
:auto-rotate="true"
output-format="blob"
accept="image/*"
#input="setImage(output , index)"
:ref="'fileUpload'+index"
>
...
And the setImage funciton :
setImage: function(output,index) {
console.log(index);
console.log(output);
return ;
this.lines[index].hasImage = true;
this.lines[index].image = output;
let formData = new FormData();
formData.append("file", output);
Ax.post(upload_route, formData, {
headers: { "Content-Type": "multipart/form-data" }
})
.then(response => {
// upload successful
})
.catch(error => console.log(error));
}
And the log result is:
The index always is 0 :(
How can i send an index when i want to upload it?
I read this passing event and index and test it but it's not working on component.
Because This is a custom event not a DOM event.
what should I do?
thanks.
Because you're actually passing the return value of setImage to the #input, not the method.
You can't just add extra parameters to setImage, as ImageUploader component just emit an image to the setImage. If you need to add extra parameters to that method, you need to create custom element that wrap ImageUploader.
It's something like this:
ImageUpload.vue
<template>
<image-uploader
:debug="0"
:autoRotate="true"
outputFormat="blob"
:preview="true"
:className="['fileinput', { 'fileinput--loaded' : hasImage }]"
:capture="false"
accept="image/*"
doNotResize="['gif', 'svg']"
#input="setImage"
v-on="listeners" />
</template>
<script>
export default {
props: {
index: {
required: true,
type: Number
}
},
data() {
return {
hasImage: false,
image: null
};
},
computed: {
listeners() {
const listeners = { ...this.$listeners };
const customs = ["input"];
customs.forEach(name => {
if (listeners.hasOwnProperty(name)) {
delete listeners[name];
}
});
return listeners;
}
},
methods: {
setImage(image) {
this.hasImage = true;
this.image = image;
this.$emit("input", this.index, image); // here, we emit two params, as index for the first argument, and the image at the second argument
}
}
};
</script>
Then, you can use that component something like this:
<template>
<div class="container">
<div v-for="(line, index) in lines" :key="index">
<image-upload :index="index" #input="setImage"/>
</div>
</div>
</template>
<script>
import ImageUpload from "./ImageUpload";
export default {
components: {
ImageUpload
},
data() {
return {
lines: ["1", "2", "3", "4"]
};
},
methods: {
setImage(index, image) {
console.log("Result", index, image);
}
}
};
</script>
See the working example: https://codesandbox.io/s/vue-template-ccn0e
Just use $event like this...
#input="setImage($event, index)"
...and you're done!
I have an area where people can upload their own user-image. But if they do not, I would like to display a default one.
After some googling, I found I can do so by doing something like -
<img :src="creatorImage" #error="defaultAvatar">
But, I am not sure how to then created a method to pass the correct (default) image into it.
I did it with a computed property, like this:
<template>
<img :src="creatorImage" #error="imageError = true"/>
</template>
<script>
...
data() {
return {
imageError: false,
defaultImage: require("#/assets/imgs/default.jpg")
};
},
computed: {
creatorImage() {
return this.imageError ? this.defaultImage : "creator-image.jpg";
}
}
...
</script>
I would suggest creating a component for this, as it sounds like something that will be used on more places.
JsFiddle example
Component
Vue.component('img-with-default', {
props: ['defaultImg'],
data: function () {
return {
defaultAvatar: this.defaultImg || 'https://cdn0.iconfinder.com/data/icons/crime-protection-people/110/Ninja-128.png'
}
},
computed:{
userImage: function() {
if(this.uploadedImg != null) {
return this.uploadedImg;
} else {
return this.defaultAvatar;
}
}
},
template: '<img :src="userImage">'
})
And using the commponent would be
HTML
<div id="editor">
<img-with-default></img-with-default>
<img-with-default default-img="https://cdn3.iconfinder.com/data/icons/avatars-15/64/_Ninja-2-128.png" ></img-with-default>
</div>
JS
new Vue({
el: '#editor'
})
With this you have the default image.
If you want you can create a component that would display passed img src or the default one.
Component
Vue.component('img-with-default', {
props: ['imgSrc'],
data: function () {
return {
imageSource: this.imgSrc || 'https://cdn0.iconfinder.com/data/icons/crime-protection-people/110/Ninja-128.png'
}
},
template: '<img :src="imageSource">'
})
and to use it
HTML
<div id="editor">
<img-with-default></img-with-default>
<img-with-default img-src="https://cdn3.iconfinder.com/data/icons/avatars-15/64/_Ninja-2-128.png" ></img-with-default>
</div>
I am using vue and element ui to upload files. But I don't know how to get upload files url (basically I want to check the file type - jpg or pdf and then do something).
<div id="app">
<el-upload action="https://jsonplaceholder.typicode.com/posts/" list-type="picture-card" :on-preview="handlePictureCardPreview" :on-remove="handleRemove">
<i class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<embed width="100%" :src="dialogImageUrl">
</el-dialog>
<p>file type: "{{ checkType() }}"</p>
</div>
var Main = {
data() {
return {
dialogImageUrl: '',
dialogVisible: false
};
},
methods: {
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
checkType(){
var filename = this.dialogImageUrl;
return filename.split('.').pop();
}
}
}
Please Help...
I have add this try to get URL..but it doesn't work..
var filename = document.getElementsByTagName("embed")[0].src;
console.log(filename);
you can use :before-upload attribute of el-upload. please take look of changed code.
<div id="app">
<el-upload action="https://jsonplaceholder.typicode.com/posts/" **:before-upload="checkType"** list-type="picture-card" :on-preview="handlePictureCardPreview" :on-remove="handleRemove">
<i class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<embed width="100%" :src="dialogImageUrl">
</el-dialog>
<p>file type: "{{ checkType() }}"</p>
</div>
var Main = {
data() {
return {
dialogImageUrl: '',
dialogVisible: false
};
},
methods: {
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
**checkType(file){**
console.log(file.type);
// do your action here based on file.type
var filename = this.dialogImageUrl;
return filename.split('.').pop();
}
}
}