I want to get the src image and bind it to my img tag, I'd create it in JS file and I imported, but nothing happened, first file is About.vue and the second one is my utils file
<template>
<div>
<Header></Header>
<main>
<section v-if="this.showAlert">
<b-alert show variant="success">
<h4 class="alert-heading">Well done!</h4>
<p>
This web-app was made by Gabriel Nunes, he did it all by himself.
All these buttons and headers that you saw on the app, was made by
him too.
</p>
<hr />
<p class="mb-0">
If you need anything from him, please contact via social netorks.
Social networks:
<img
:src="this.showImg.facebook.src"
:width="this.showImg.facebook.width"
:height="this.showImg.facebook.height"
/>
</p>
<p class="mb-1">
<img
:src="this.showImg.github.src"
:width="this.showImg.github.width"
:height="this.showImg.github.height"
/>
</p>
</b-alert>
</section>
<section v-if="!this.showAlert">
<b-alert show variant="secondary">
<h4 class="alert-heading">Well done!</h4>
<p>
Aww yeah, you successfully read this important alert message. This
example text is going to run a bit longer so that you can see how
spacing within an alert works with this kind of content.
</p>
<hr />
<p class="mb-0">
Whenever you need to, be sure to use margin utilities to keep things
nice and tidy.
</p>
</b-alert>
</section>
</main>
</div>
</template>
<script>
import Header from "./Header.vue";
import { pathImgObj } from "../../utils.js";
export default {
components: {
Header,
},
data() {
return {
showImg: {},
showAlert: Boolean,
};
},
created() {
this.showAlert = confirm("Are you sure about this?");
this.showImg = { ...pathImgObj };
},
methods: {},
};
</script>
<style>
</style>
Utils file js
export const config = {
home: 'Home',
anime: 'Animes',
faq: 'FAQs',
about: 'About'
}
export const pathImgObj = {
facebook: {
src: `./assets/img/facebook.png`,
width: '30px',
height: '30px'
},
github: {
src: `./assets/img/github.png`,
height: '30px',
width: '30px'
}
}
Expected result: get the src, width and height from utils file and pass it to my About.vue
How can I do this?
My results:
When a URL is required or imported, Webpack processes the URL, and decides what to do with it. For image URLs, Webpack finds the image, transforms it (e.g., image scaling and optimization), puts the result in an output directory, and returns the result's URL (e.g., dist/img/foo.abcd123.jpg).
vue-loader automatically requires only static URLs of <img>.src:
<img src="#/assets/foo.jpg"> ✅
<img :src="'#/assets/' + imgUrl1"> ❌
<img :src="imgUrl2"> ❌
export default {
data() {
return {
imgUrl1: 'foo.jpg',
imgUrl2: '#/assets/foo.jpg',
}
}
}
Dynamically bound <img>.src must be manually required either in the binding value or in the <script> block:
<img :src="require('#/assets/' + imgUrl1)"> ✅
<img :src="require(imgUrl2)"> ✅
<img :src="imgUrl3"> ✅
export default {
data() {
return {
imgUrl1: 'foo.jpg',
imgUrl2: '#/assets/foo.jpg',
imgUrl3: require('#/assets/foo.jpg'),
}
}
}
Since the URLs in the utils file are dynamically bound in the template, vue-loader does not require them, and thus they're treated as static assets in public/. For example, a static URL of ./assets/foo.jpg refers to public/assets/foo.jpg.
Related
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
I have created object like that
export const homeObjOne ={
lightBg: false,
lightText: true,
lightTextDesc: true,
topLine:'Explore DrukBox', // - working correctly
headLine: 'Unlimited printing <br> with us',
description: 'Lets <br> begin!', // - output: Lets <br> begin!(with br)
buttonLabel: 'Get Started',
imgStart: '',
img: './assets/svg-1.svg',
alt: 'DrukBox'
}
and bringing it to component like that
function HeroSection({
lightBg,topLine,lightText,lightTextDesc,headLine,description,buttonLabel,img, alt, imgStart
}) {
return (
<div className={lightBg ? 'home__hero-section' : 'home__hero-section darkBg'}>
<div className="container">
<div className="row home__hero-row"
style={{display:'flex',flexDirection: imgStart === 'start' ? 'row-reverse' : 'row'}}
>
And so on
<div className="home__hero-img-wrapper">
<img src={img} alt={alt}/>
</div>
</div>
</div>
</div>
)
}
but in the object my html code not parses i tried all types ',",`
import {homeObjOne} from './Data'
function Home() {
return (
<div>
<HeroSection {...homeObjOne} />
</div>
)
}
export default Home
thats how i import object
You have created addPagesObjOne as a JS Object.
To access the properties within this object and assuming addPagesObjOne has been:
Imported into the component with your JSX or
Within the component file
Then to correctly reference a property see this example:
<img src={img} alt={alt}/>
will become
<img src={addPagesObjOne.img} alt={addPagesObjOne.alt}/>
Update:
I can see that you have provided an update to how you have laid out your code, I created a quick sandbox here your code works fine. Maybe your assest is not in the correct place?
I'm relatively new to react and javascript (I'm usually backend Java). I'm currently trying to make an image gallery, where the subsections are clicked on and thumbnails of the images within each section are displayed. The thumbnails can then be clicked on and open a lightbox (I'm utilizing simple-react-lightbox for this and am on the latest version).
It works, but inconsistently. Sometimes when I click on the thumbnail, instead of throwing up the lightbox and being able to click through the images, it takes me directly to the full sized image.
My nested array with the image data, (imports of images omitted)
const GALLERIES =[
{
name: 'Beaded Jewelry',
id: 'beadwork',
description: 'placeholder',
resources:[
{
id: 1,
thumbnail: bluependant,
url: blue,
title: 'Blue Swarovski Pendant'
},
{
id: 2,
thumbnail: greenpendant,
url:green,
title: 'Green Swarovski Pendant'
}
]
},
{
name: 'Wire Jewelry',
id: 'wirewrapped',
description: 'placeholder #2',
resources:[
{
id: 'wire1',
thumbnail: wire1Thumb,
url: wireWrap1,
title: 'placholder 1'
},
{
id: 'wire2',
thumbnail: wire2Thumb,
url:wireWrap2,
title: 'placholder 1'
}
]
}
];
export default GALLERIES
And the js that I'm trying to make work consistently.
import React from 'react';
import '../css/gallery.css';
import '../css/jewelry_main.css';
import GALLERIES from '../data/galleries';
import SimpleReactLightbox from "simple-react-lightbox";
import { SRLWrapper } from "simple-react-lightbox";
import {Link } from 'react-router-dom';
const Gallery = props =>{
const{thumbnail, url, title } = props.subgallery;
return(
<div className="gallery">
<a href={url} data-attribute="SRL">
<img src={thumbnail} alt={title} />
</a>
</div>
)
}
const JewelryGallery = ({match}) =>{
const gallery = GALLERIES.find(({ id }) => id === match.params.keyword)
return(
<div>
<div className="frosted">
<p>{gallery.description}</p>
</div>
<SimpleReactLightbox>
<SRLWrapper>
{
gallery.resources.map((SUBGALLERY) =>{
return(
<Gallery key = {SUBGALLERY.id} subgallery={SUBGALLERY} />
)
})
}
</SRLWrapper>
</SimpleReactLightbox>
</div>
);
}
export default JewelryGallery;
Any insight or wisdom would be greatly appreciated! Thank you!
UPDATE EDIT: I noticed something, the first subgallery I click into will always present with the lightbox, but the second one, consistently fails and instead goes directly to the fullsize of whichever image I have clicked on. (It doesn't matter which of the two I pick first, the second always fails.) But I can't discern why the lightbox would not get applied to the second gallery I select.
There are only two things I can see that differ from the documentation for the simple-react-lightbox package.
First thing is, with the latest version, you only need to use the <SRLWrapper> component. You have both the <SRLWrapper> and the <SimpleReactLightbox> component in use. Perhaps try getting rid of the old version if you have the latest version of the package installed.
Second thing is the structure of your Gallery component return has the div wrapping the elements. I'm not sure if this would cause any problems but, to get as close as possible to the example in the docs you could try using a fragment instead of a div.
const{thumbnail, url, title } = props.subgallery;
return(
<>
<a href={url} data-attribute="SRL">
<img src={thumbnail} alt={title} />
</a>
</>
)
I haven't used the package so this is a bit of speculation. Hope it leads you in the right direction though.
EDIT
I think I misunderstood this library a bit. You do need both of those components. It looks like if you want to display full size images, you would do it the way you have it currently. However, if you want to use the lightbox feature with the nav at the bottom you would need to do something like:
<SimpleReactLightbox>
<SRLWrapper>
<div id="content-page-one" className="container content">
<div className="row">
{
gallery.resources.map((SUBGALLERY) =>{
return(
<Gallery key = {SUBGALLERY.id} subgallery={SUBGALLERY} />
)
})
}
</div>
</div>
</SRLWrapper>
</SimpleReactLightbox>
And then you would use div instead of an anchor tag:
<div className="col-md-6 col-12 col-image-half">
<img src={thumbnail} alt={title} />
</div>
This is pulled from the Code Sandbox examples they have. I would take a closer look there and see if they have the exact setup you're looking for. Notice also that they are using the Bootstrap styling framework as well, so in order for those styles to work you would need to install bootstrap to your dependencies.
I have a child component sending data via an event to a parent component in VueJS. From the parent component, I am routing the data (or trying to route the data...) to a sibling of the child and create new components with the data sent from the child.
I use a dictionary to group the data for various reasons, then push the dictionary into an array. A v-for loop loops thru the array and populates the previously mentioned new components with data found in that array. I probably don't need to do it this way, but that's how I'm doing it. I am open to alternatives.
Anyway, it doesn't work great. So far I'm only able to get one of the three strings I need to show up where I want it to. I'll explain more after I post the code.
Already tried:
A dozen different versions of the code, including creating a simple v-for in a list to do the job, and various versions with/without a dictionary or array.
In my research for the problem I've gone through the VueJS docs, Googled a few things, and found nothing.
In App.vue (I tried to remove all the irrelevant stuff):
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<TweetDeck v-on:messageFromTweetDeck="msgReceived($event)"/>
<!-- <ul>
<li v-for="(tweet, index) in tweets" :key="index">{{ tweet }}</li>
</ul>-->
<TwitterMsg v-for="(tweet, index) in tweets" :key="index"
:name="tweet.name" :handle="tweet.handle" tsp=3 :msg="tweet.tweet" />
<TwitterMsg name="aaa" handle='aaa'
tsp=50 msg="hey this is a message on twitter"/>
<input type="text" v-model="placeholderText"/>
</div>
</template>
<script>
import TwitterMsg from './components/TwitterMsg.vue'
import TweetDeck from './components/TweetDeck.vue'
export default {
name: 'app',
components: {
TwitterMsg,
TweetDeck
},
data: function() {
return {
tweets: [],
message: "",
placeholderText: ""
}
},
methods: {
msgReceived(theTweet, name, handle) {
this.tweets.push({tweet: theTweet, name: name, handle: handle})
}
}
}
</script>
And in TweetDeck.vue:
<template>
<div>
<input type='text' v-model="yourName">
<input type='text' v-model="yourHandle">
<input type='text' v-model="yourTweet"/>
<button type='button' #click="sendTweet()">Tweet</button>
</div>
</template>
<script>
export default {
name: "TweetDeck",
data: function() {
return {
yourName: "Your name here",
yourHandle: "Your twitter handle",
yourTweet: "What's going on?"
}
},
methods: {
sendTweet() {
this.$emit('messageFromTweetDeck', this.yourTweet, this.yourName, this.yourHandle);
}
}
}
</script>
You can also see the mostly unimportant TwitterMsg.vue here (I am trying to copy Twitter for learning purposes:
<template>
<div>
<h4>{{ name }}</h4>
<span>#{{ handle }}</span>
<span> {{ tsp }}</span> <!-- Time Since Posting = tsp -->
<span>{{ msg }}</span>
<img src='../assets/twit_reply.png'/><span>1</span>
<img src="../assets/twit_retweet.png"/><span>2</span>
<img src="../assets/twit_fave.png"/><span>3</span>
</div>
</template>
<script>
export default {
name: "TwitterMsg",
props: {
name: String,
handle: String,
tsp: String,
msg: String
}
}
</script>
<style>
img {
width: 30px;
height: 30px;
}
</style>
Expected result:
The code populates a new TwitterMsg component with appropriate name, handle and message data each time I click the "Tweet" button.
Actual results:
My code fails to help the name and handle strings make it from the input text box in TweetDeck.vue all the way to their home in TwitterMsg.vue.
I will say that this.yourTweet in TweetDeck.vue DOES manage to make it all the way to its destination, which is good -- though it makes me wonder why the other two pieces of data didn't follow suite.
Totally lost. Also just in my first month of VueJS so it's pretty good that I can even make one string appear where I want it to. \o/
First, you need to remove the $event parameter
<TweetDeck v-on:messageFromTweetDeck="msgReceived"/>
Second, you can optimize the data format passed to the parent component:
sendTweet() {
this.$emit("messageFromTweetDeck",
{ tweet: this.yourTweet, name: this.yourName, handle: this.yourHandle }
);
}
And then modify your msgReceived method:
msgReceived(childData) {
this.tweets.push(childData);
}
Link: codesandbox
Hope to help you:)
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