How to dynamically display an image in VueJS? - javascript

Please see here the relations between components
How to pass value from one child component to another in VueJS?
The snippet bellow not giving an error and not displaying the image
<img v-bind:src="image_url" />
Code:
<template>
<div>
<img v-bind:src="image_url" />
</div>
</template>
<script>
export default {
props: ["image_url"]
};
</script>
image_url comes from another component and in VueJS developer's tool I was able to confirm the value is an url. Looks like something wrong with the way how I'm trying to render a dynamic image.

You have to expose your images to your web server. Hopefully Vue-cli does that for you. You have to move your assets folder from src to the public folder.
More info on https://cli.vuejs.org/guide/html-and-static-assets.html#static-assets-handling

Don't forget to add.
<div v-if="image_url">
<img v-bind:src="image_url" />
</div>

Might worked on yours. Make a watcher for that to update again the props value an rerender it in your component.
export default {
props: ["image_url"],
watch: {
image_url(val){
this.image_url = val
},
}
};

Related

(Nuxt) Vue component doesn't show up until page refresh

I'm storing nav items in my Vuex store and iterating over them for conditional output, in the form of a Vue/Bulma component, as follows:
<b-navbar-item
v-for='(obj, token) in $store.state.nav'
v-if='privatePage'
class=nav-link
tag=NuxtLink
:to=token
:key=token
>
{{obj.text}}
</b-navbar-item>
As shown, it should be output only if the component's privatePage data item resolves to true, which it does:
export default {
data: ctx => ({
privatePage: ctx.$store.state.privateRoutes.includes(ctx.$route.name)
})
}
The problem I have is when I run the dev server (with ssr: false) the component doesn't show up initially when I navigate to the page via a NuxtLink tag. If I navigate to the page manually, or refresh it, the component shows.
I've seen this before in Nuxt and am not sure what causes it. Does anyone know?
recommendation :
use mapState and other vuex mapping helper to have more readable code :).
dont use v-for and v-if at the same element
use "nuxt-link" for your tag
use / for to (if your addresses dont have trailing slash)
<template v-if='privatePage'>
<b-navbar-item
v-for='(obj, token) in nav'
class=nav-link
tag="nuxt-link"
:to="token" Or "`/${token}`"
:key="token"
>
{{obj.text}}
</b-navbar-item>
</template>
and in your script :
<script>
import {mapState} from 'vuex'
export default{
data(){
return {
privatePage: false
}
},
computed:{
...mapState(['privateRoutes','nav'])
},
mounted(){
// it's better to use name as a query or params to the $route
this.privatePage = this.privateRoutes.includes(this.$route.name)
}
}
</script>
and finally if it couldn't have help you , I suggest to inspect your page via dev tools and see what is the rendered component in html. it should be an <a> tag with href property. In addition, I think you can add the link address (that work with refresh and not by nuxt link) to your question, because maybe the created href is not true in navbar-item.
NOTE: token is index of nav array . so your url with be for example yourSite.com/1.so it's what you want?
This question has been answered here: https://stackoverflow.com/a/72500720/12747502
In addition, the solution to my problem was a commented part of my HTML that was outside the wrapper div.
Example:
<template>
<!-- <div>THIS CREATES THE PROBLEM</div> -->
<div id='wrapper'> main content here </div>
</template>
Correct way:
<template>
<div id='wrapper'>
<!-- <div>THIS CREATES THE PROBLEM</div> -->
main content here
</div>
</template>

How to save image link in when using 'require' to display image in VueJS?

I am trying to create a page where I show Pizza items with their images. The Pizza object is saved in the DB with a field imgUrl. The image is not getting displayed but I see the alt text that I provided but I can see in the console that the image link is correct.
Right now, the imgUrl field in the database has data like ../assets/images/pizza.jpg. Should I instead save require(../assets/images/pizza.jpg) in the db. That looks weird. Here is the code, please look at the mounted method.
<template>
<div>
<div class="class">
<span><h1>All you can eat Menu.</h1></span>
<div class="container">
<div class="box" v-for="item in pizzaList" :key="item.id">
<div>
<img :src="item.imgUrl" alt="Image"/>
<div>
<a class="btn" #mouseenter="$event.currentTarget.style.background = '#EF6B7F'"
#mouseleave="$event.currentTarget.style.background = '#e31837' ">Buy Now</a>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
data () {
return {
pizzaList: []
}
},
mounted: function () {
axios.get('http://localhost:8081/api/pizza/all')
.then(response => {
this.pizzaList = response.data;
})
.catch(e => {
console.log(e);
})
}
}
</script>
I have already read
Vue and API: Displaying Image
Image path in Vue JS
How to reference static assets within vue javascript
but what these answers are telling is how to do when we have hardcoded the url, we should encapsulate it with require but they do not tell when we are getting the link from the DB, how do we put require in the html tag.
I hope my question was clear. Please ask for details if you need. thanks
The reason it was not working was because
Webpack's require() needs at least some part of the file path to be completely static and we should "make only part of the path dynamic"
that means you cannot put the entire image path in the DB and in the UI pass it to require and expect it to work
I replaced
<img :src="require(`${item.imgUrl}`)" alt="Image"/>
where item.imgUrl = '../assets/entities/pizza/pizza_1.jpg' (which is the entire image path relative to the component)
by
<img :src="require(`../assets${item.imgUrl}`)" alt="Image"/>
where item.imgUrl = '/entities/pizza/pizza_1.jpg'
This answer mentioned by Michal Levy up in the comments explains all this
https://stackoverflow.com/a/64208406/8147680

Vue template isn't rendering in for loop

So after following a beginner Vue tutorial to setup a Todo app, I decided to try to adapt some parts of it for a website I'm trying to make. What I'm stuck on is that despite everything saying my for-loop is supposed to work, it doesn't.
The project itself was created using the vue-cli, and most of the code copy-pasted from the tutorial. (which is working fine with its own for-loop)
It seems like the data might be not passed onto the template maybe?
I have tried:
having the info inside the props and data sections
passing whole object and only parameters to the template
tried with hard-coded values inside array which is iterated on
(After setting up a new vue-cli project:)
App.vue:
<template>
<div id="app">
<create-section v-on:create-section="addSection" />
<section v-for="section in sections" v-bind:key="section.title" :info="section"></section>
</div>
</template>
<script>
import CreateSection from "./components/CreateSection";
import Section from "./components/Section";
export default {
name: "App",
components: {
CreateSection,
Section
},
data() {
return {
sections: []
};
},
methods: {
addSection(section) {
this.sections.push({
title: section.title,
description: section.description
});
console.log(
"Added to sections! : " + section.title + " | " + section.description
);
console.log("Sections length: " + this.sections.length);
}
}
};
</script>
Section.vue
<template>
<div class="ui centered card">
<div class="content">
<div class="header">{{ info.title }}</div>
<div>{{ info.description }}</div>
</div>
</div>
</template>
<script type = "text/javascript" >
export default {
props: {info: Object},
data() {
return {};
}
};
</script>
Expected result:
Display Section template on the website (after creating it with addSection that another script calls. Not included for brevity)
Actual result:
Nothing is displayed, only a empty tag is added
I believe the problem is that you've called it Section. As <section> is a standard HTML element you can't use it as a component name.
There is a warning built into the library but it seems to be case sensitive, which isn't entirely helpful. Try changing your components section to this:
components: {
CreateSection,
section: Section
},
You should then see the warning.
The fix would just be to call it something else.
This is mentioned in the first entry in the style guide:
https://v2.vuejs.org/v2/style-guide/#Multi-word-component-names-essential
section is an existing HTML5 element, you should name your section component something different.
If you really want to name the component Section, register it as 'v-section'
The problem is that when you do the loop in the <section v-for="section in sections" v-bind:key="section.title" :info="section"></section> the Array sections is not ready, there is nothing there.. so when you add new things to this array you need to trigger (computed prop) to send again the data to the section component.
Aside from the issue with using an existing HTML5 command as a name for your Vue component (you should change that to another name by the way), you should also look into how you declared the props within Section.vue. The code below shows the correct way to do it:
<script type = "text/javascript" >
export default {
props: ['info'],
data() {
return {};
}
};
</script>
The props take in the name of the property being declared from the parent component and should be a string.
Hope this helps.

How to use an image as a button in Vue.js?

I'm trying to make a login button as a single-file-component in Vue.js (it's a Rails app with a Vue.js front-end). If you click this button, it's supposed to take you to the an external provider's login page.
How can I use an image as a button? I'm guessing you use v-on:click for the actual redirect, but I'm stuck there.
Right now, this code below shows a hardcoded button that looks like img(src="../assets/img/login_button.png"). You can click on it, but that's obviously not what I want. I want to show the actual png image, not the path.
// LoginButton.vue
<template lang="pug">
#login-button
<button v-on:click="redirect_to_login">img(src="../assets/img/login_button.png")</button>
</template>
<script lang="ts">
import { Vue, Component } from 'vue-property-decorator';
#Component
export default class LoginButton extends Vue{
redirect_to_login():void{ // I haven't written this method yet
}
}
</script>
Is there any reason you can't just use normal HTML image inside your button? I haven't used pug before.
<button v-on:click="redirect_to_login"><img src="../assets/img/login_button.png" /></button
Though since you're using Vue and not an actual HTML form you might not even need a button you could just add the click binding to the image instead
<img src="../assets/img/login_button.png" v-on:click="redirect_to_login" />
I am not familiar with pug, so I don't know what the correct syntax you'll need is. But you can use the <router-link> tag to set the route. For example (using Vuetify)
<router-link to="/">
<v-img src="/path/to/img.gif"/>
</router-link>
Either you can use:
<a #click="Redirect">
<img src='IMAGE_SRC' />
</a>
or
<img #click="Redirect" src='IMAGE_SRC'/>
new Vue({
el: '#app',
methods:
{
Redirect()
{
window.location.href = "https://jsfiddle.net/";
//or
//this.$router.push('LINK_HERE'); // if ur using router
}
}
})
Demo LINK:
https://jsfiddle.net/snxohqa3/5/

Facebook Create React App Build - Add Image As Prop Type

I have a component comment.js
export default function Comment (props) {
return (
<div className="comment-wrapper">
<img src={props.userImage} />
<p className="comment">{props.commentTitle}</p>
</div>
);
}
So I just simply want to have that component in the parent component as
<Comment userImage="IMAGE_LINK" commentTitle="BLAH BLAH" />
Again, I am using the Create-React-App build system from facebook. With that being said I know I can hard code an image using the following
<img src={require(`./images/MY-IMAGE.png`)} />
The code above works perfectly fine for the test image I am trying to load. However, when needed dynamically for the component the issue gets a bit more complex.
Now with the comment.js component above, I cannot do
<img src={require("./images" + {props.userImage})} />
I have taken a look at one thread on this site as well as reading this blog post on the issue and can still not come to a conclusion.
How can I handle image assets being passed as props to a component, in this case?
you can use import
// parent component
import MenuImage from '/img/menu.png'
<Comment image={MenuImage} commentTitle="Title"} />
then on Comment component
export default props => (
<img src={props.image} alt='' />
)

Categories

Resources