vuejs set img src by using current route name - vue.js

There is a file contains images.Every pictures'name is a route name. I want to change the img src attribute by current route name.But I can not get the full path,only can get the picture name.
<template>
<!-- footer -->
<div class="index-footer">
<img v-bind:src = "$route.name" />
</div>
</template>
<script>
import { Carousel } from 'iview'
// export default {
// components: { Carousel }
// }
export default {
name: 'index',
data () {
return {
index: '/static/img/footer/index.png',
more: '/static/img/footer/index.png',
product: '/static/img/footer/index.png',
information: '/static/img/footer/index.png',
news: '/static/img/footer/index.png',
down: '/static/img/footer/index.png',
enterprise: '/static/img/footer/enterprise.png',
value3: 0,
setting: {
autoplay: true,
autoplaySpeed: 4000,
dots: 'inside',
trigger: 'hover',
arrow: 'hover'
},
scrolled: false
}
},
components: {
Carousel
}
}
</script>

You're not binding the src at all. You need to use the binding directive to bind the src.
Like this
<img :src="index">
or this
<img v-bind:src="index">

Use this[this.$route.name] or this[$route.name] as the binding text for v-bind.
v-bind evals the text you pass in as javascript code (expression, to be more exact), with a bit extra trick of considering the variables in the expression to be members of the view-model (aka this).
The tricky part here is that we want this[this.$route.name], which is confusing to translate to the v-bind text with the "I'll fill in the this for you" rule Vue provides. I tested a bit and found both this[this.$route.name] and this[$route.name] works. Not sure why they work, however. :/

Related

img src is not working within v-for loop when using list items in vue js [duplicate]

I got a parent component which sends a data object to the children component like this:
<child object-data=" url: 'url here', title: 'Title'"></child>
Then on my children component, I get this object data by doing:
<script>
export default {
props: [
'objectData'
]
}
</script>
Now, for some reason, I can use title without any problem like this {{ objectData.title }} and shows up.
But when it comes to the URL inside an img tag it's not rendering the image.
I attempted doing the following:
<img :src="objectData.url"/> <--- not rendering
<img v-bind:src="objectData.url"/> <--- not rendering
<img v-bind:src="require(objectData.url)"/> <-- throws a warning error because it's not a path but an object I guess.
<img v-bind:src="{objectData.url}"/> <--- throws an error
<img v-bind:src="{{objectData.url}}"/> <--- throws an error
When I check on the dom element, it doesn't even contain a src attribute afterwards.
If I write down the URL without an object, it works.
<img v-bind:src="src/assets/images/icon.png"/>
But I want my URL to come from a parent component.
Any ideas on how to solve this? I added the url-loader on my webpack file:
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader'
}
I also attempted returning objectData.url from a computed/methods fuction:
computed: {
getImageUrl: function() {
return objectData.url;
}
}
And then use it like :src=“getImageUrl” or :src=“{{getImageUrl}}” and I wasn’t lucky either.
I faced the same issue and i fixed it by using require function :
in the parent component App.vue :
<carousel-posts :posts="posts" />
export default {
name: "app",
data() {
return {
posts: [
{
img: require("./assets/logo.png"),
title: "Title 1",
subTitle: "Sub Title 1",
body:"lorem ipsum ..."
}
...
]
};
}
...
}
in the child component i loop through the posts and bind the image src as follows :
<div class="card-body" v-for="(post,idx) in posts" >
<img class="card-img" :src="post.img" />
...
</div>
<script>
export default {
props: ["posts"],
...
So in your case you should have something like :
<child :object-data="objectData"></child>
...
data(){
return{
dataObject:{
url: require('./assets/someimg.png'),
title: 'Title'
}
}
}
Update :
my project tree :
src
|_assets
| |_logo.png
|_components
| |_CarouselPosts.vue
|_App.vue
Two alternatives:
Static links that vue resolves. But they're src-based and don't work with webpack / file-loader:
<img :src="'../assets/filename.png'"/>
Works with webpack. Note the ".default" at the end:
<img :src="require('../assets/filename.png').default"/>
Documentation relevant effective Nov 2019:
https://github.com/vuejs/vue-loader/issues/1612

How do I programmatically bind in video player URLs in Nuxt/Vue?

I was looking for an idea of how to programmatically bind in video player urls. I understand the idea of using img and doing v-for and a :src, but the url for my videos get put in the data of the script. Is it possible to bind and make these programmatic as well? Here is an example of a working script now, but I just have to replace this as a component for every single video manually.
<template>
<div class="player">
<client-only>
<video-player
ref="videoPlayer"
:options="playerOptions"
/>
</client-only>
</div>
</template>
<script>
export default {
name: "index",
data() {
return {
playerOptions: {
sources: [{
type: 'application/x-mpegurl',
src: 'myvideo.m3u8'
}],
The above code is working, but I need to have a component for every single video. Then in each component put the same code, but change the name of the src for the m3u8 video. Ideally, I would want to just pass something from an api into the src of the m3u8 and create one dynamic component. The question is, how would I make this dynamic component?
I tried something like this, but couldnt do a :src in the script.
<template>
<div class="player">
<client-only>
<video-player
ref="videoPlayer"
:options="playerOptions"
/>
</client-only>
</div>
</template>
<script>
export default {
name: "index",
data() {
return {
playerOptions: {
sources: [{
type: 'application/x-mpegurl',
:src: video.url
}],
#tomdale I'm not sure if i'm understanding your question correctly, but if you want something dynamic you're probably best to remove playerOptions from your data() property and turn it into a computed property.
It could then look something like this,
computed: {
playerOptions() {
return {
sources: [{
type: 'application/x-mpegurl',
src: this.video.url
}]
}
},
}
Your question doesn't really show where you're getting the video and video.url data from, but if the component is working with a collection of video data, you could do something like,
playerOptions() {
let sources = []
let i = 0
while (i < this.videos.length) {
sources.push({
type: 'application/x-mpegurl',
src: this.videos[i].url
})
i++
}
return sources
},
You'll be be able to reference playerOptions the same way that you were in when it was in data(), ie this.playerOptions, however now it will be dynamic.

How can I can show a div if an object doesn't have a value outside of the object scope

I have a small Nuxt issue that I can't work out how to get around.
Essentially, I have an object (used for a carousel slider).
<template>
<div
:class="[$style.swiperSlide, 'swiper-slide']"
v-for="slide in slides"
:key="slide.id">
<nuxt-img
:class="[$style.img]"
:alt="slide.alt"
:src="imgSources(slide)"
sizes="sm:100vw"
/>
<div :class="[$style.info, 'info-b']" v-if="slide.info">
{{ slide.info }}
</div>
</div>
<button :class="[$style.infoOpen]"
#click="showTab"
v-if="slideInfoAvailable"
>
Close
</button>
</template>
<script>
export default {
props: {
slides: {
type: Array,
required: true,
default: () => []
}
},
computed: {
slideInfoAvailable() {
return this.slide?.info
}
},
mounted() {
const swiper = new Swiper(".swiper-container", {
. . .
});
},
methods: {
imgSources(slide) {
return `/img${slide.imgPath}.jpg`;
},
};
</script>
All works o.k, the problem is that I have a button outside of this v-for that I need to only be visible if there's slide.info but because this div is outside of the v-for it can't tell if it's available.
Cannot read property 'info' of undefined
The easiest way out of this is to add the button inside of the slider - but I can't for Z-index CSS issues. It has to be outside of the 'slider' div.
Any ideas how I can only show the button if there's slide.info? For some of my slides, there won't be.
<slider
:slides="[
{
imgPath: '/demo',
info: 'Demo info for this slide',
alt: 'Homepage'
},
{
imgPath: '/demo2',
alt: 'Homepage'
},
]"
/>
One way I could do it would be to see if .slide-active .style.info exists. If it doesn't exist then I can hide the button as slide-active is added to the active div by the slider API.
The issue is coming from the fact that you probably have some async fetching and that slides are not available upon initial render. To prevent this, you can use a computed with some optional chaining like this
export default {
computed: {
slideInfoAvailable() {
return this.slide?.info
}
}
}
Then, call it like this
<button :class="[$style.infoOpen]" #click="showTab" v-if="slideInfoAvailable">
You cannot use ?. directly in the template.
You could also do the classic way of
<button :class="[$style.infoOpen]" #click="showTab" v-if="slide && slide.info">
but it does not look as sexy IMO (but you do not need any computed).
And yeah, for this kind of thing, better to handle it with Vue than relying on some hacky dirty CSS tricks!

How to add more than one attributes to an element dynamically in vuejs

I am trying to think of a way to add more than one attribute dynamically.
Below is a mockup code for that.
If I loop through attributes and try to add it to img tag then I'll have more than one image tag and that I don't want. I want to have all the attributes inside the array to be on the same element.
Any help would be appreciated.
<template>
<img />
</template>
<script>
export default {
data(){
attributes: [
{class: 'main'},
{src: '/somthing/img.jpg'}
]
}
}
</script>
You can use v-bind for that purpose. Example:
<template>
<img v-bind="attributes"/>
</template>
<script>
export default {
data(){
return {
attributes: {
class: 'main',
src: '/somthing/img.jpg'
}
}
}
}
</script>
If you would like to also dynamicly bind event's listeners you could use v-on same way as I did with v-bind

Setting props of child component in vue

I'm following the example here of using a Vue template as a Kendo UI template in their components:
https://www.telerik.com/kendo-vue-ui/components/framework/vue-templates/
The example isn't very clear on how to supply properties to components that are rendered with this method (as opposed to rendering right in the template). I need to supply a single value determined in the parent to all instances of this child component, and I also need to subscribe to emitted events from the child component. My assumption is that there's an overload to Vue.component() that lets me access this functionality?
Edit:
Specifically what I am looking for is a way to have a header template for each column created from a Vue component. I need each column's template to receive data from the parent so I know how to construct it, and I also need each column's template to report an event back to the parent.
I think the key point is Step 3 in the link you attached (Kendo Vue Template Usage). (Never touch Kendo Before, if anything wrong, correct me, thanks.)
First, please open this Vue kendo Sandbox, you will find one dropdownlist then each option is one button plus one text. If you click the button, it will call one method in MyTemplate.vue and another Method at DropDownStyle.vue, then its background of each option is blue which passed from DropDownStyle.vue.
Kendo will bind this function of Step 3 to its attribute=template, then fisrt parameter (and only one) is each element of the data-source.
Then this function need to return one object including template and templateArgs, then Kendo construct it.
So my solution is add your function/callback/styles into templateArgs, then do what you need at MyTemplate.vue.
Below is the codes extended from Step 3.
methods: {
getMyTemplate: function (e) {
// parameter=e: it is the value of each element of the dropdown
e.callback = this.eventCallback
e.styles="background-color:blue"
return {
template: MyTemplate,
templateArgs: e
}
},
eventCallback: function (data) {
console.log(this.dropdowns)
}
}
Below is MyTemplate.vue.
<template>
<span :style="templateArgs.styles">
<button #click="buttonClick();templateArgs.callback()">{{templateArgs.value}}</button>
{{templateArgs.text}}
</span>
</template>
<script>
export default {
name: 'template1',
methods: {
buttonClick: function (e) {
console.log('props',this.templateArgs.styles)
}
},
data () {
return {
templateArgs: {
callback:function(){
console.log('Test')
},
styles:''
}
}
}
}
</script>
Very odd design choice in terms of passing the template in like they do. Avoiding the KendoUI and focusing on VueJS methods - could you use provide/inject? Providing the value in the parent and injecting in any of the children?
Also a plugin could be created to keep track of events or values you want available to all components in the application. In essence the plugin would be a service. A singleton object that is only instantiated once.
The documentation is indeed lacking. I agree with you on that. I took a different approach with templating for Kendo UI component and got this working: https://codesandbox.io/s/github/ariellephan/vue-kendoui-template
To start, I have this dropdown component that utilizes Kendo dropdown list component:
<template>
<div>
<p>Style with template {{template}}</p>
<kendo-dropdownlist
:template="template"
:headerTemplate="headerTemplate"
:data-source="dataSourceArray"
:data-text-field="'text'"
:data-value-field="'value'"
:filter="'contains'">
</kendo-dropdownlist>
</div>
</template>
<script>
export default {
name: "Dropdown",
props: ["dataSourceArray", "template", "headerTemplate"],
data() {
return {
value: "Click Me",
text: "I'm in Template template"
};
}
};
</script>
To render different styles/templates, I parsed in props from the parent component. In this case, DropdownStyles
<template>
<div id="DropdownStyles">
<h1>KendoUI dropdown instances with different templates</h1>
<Dropdown
v-for="dropdown in dropdowns"
v-bind:key="dropdown.id"
v-bind:title="dropdown.title"
v-bind:data-source-array="dropdown.dataSourceArray"
v-bind:template="dropdown.template"
v-bind:headerTemplate="dropdown.headerTemplate"
></Dropdown>
</div>
</template>
<script>
import Dropdown from "./Dropdown";
import DropdownTemplate from "./DropdownTemplate";
export default {
name: "DropdownStyles",
components: { Dropdown },
data() {
return {
dropdowns: [
{
id: 1,
title: "x style",
dataSourceArray: [
"Football",
"Tennis",
"Basketball",
"Baseball",
"Cricket",
"Field Hockey",
"Volleyball"
],
template: `<strong class="custom-dropdown">x #:data#</strong>`,
headerTemplate: DropdownTemplate.template
},
{
id: 2,
title: "+ style",
dataSourceArray: [
"Football",
"Tennis",
"Basketball",
"Baseball",
"Cricket",
"Field Hockey",
"Volleyball"
],
template: `<strong class="custom-dropdown">+ #:data#</strong>`,
headerTemplate: `<div><h3 style="padding-left:10px;">Sports 2</h3></div>`
}
]
};
}
};
</script>
You can move the template into its own file or function. For example, the first drop down is using DropdownTemplate for its headerTemplate:
DropdownTemplate.vue
<script>
export default {
name: "DropdownTemplate",
props: ["header"],
template: `<div>
<div><h3>Sports 1</h3></div>
</div>`,
data() {
return {};
}
};
</script>
<style scoped>
h3 {
padding-left: 10px;
}
</style>