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.
Related
In my project i have make a main.jsx in which i provide image link and description in array of 3 item. then i take those to another component name Photo through Photowall.jsx . But image is showing of alt. not the imgaeLink
<figure className='figure'>
<img src={post.imageLink} alt={post.description}/>
</figure>
my main.jsx -
import Header from './Header'
import Photowall from './Photowall'
const posts = [
{
id:"0",
description:"Konoha green beast",
imageLink:"https://www.google.com/imgres?imgurl=http%3A%2F%2Fpm1.narvii.com%2F6439%2Fecfa73c34db4039a4dd92481ea16a180a18608ed_00.jpg&imgrefurl=https%3A%2F%2Faminoapps.com%2Fc%2Fnaruto%2Fpage%2Fitem%2Fmight-guy%2FpP62_LZupInrJwxPJ6ljo7bjQGaD4JvLQW&tbnid=yS1-MAqQpVQZ2M&vet=12ahUKEwiW95Dlj9v2AhXpNbcAHXJGBZQQMygJegUIARDpAQ..i&docid=F6A5JxmHTsx4zM&w=400&h=300&q=guy%20sensei&ved=2ahUKEwiW95Dlj9v2AhXpNbcAHXJGBZQQMygJegUIARDpAQ"
},
{
id:"1",
description:"again Uchiha",
imageLink:"tobi.png"
},
{
id:"2",
description:"rasenshuriken",
imageLink:"https://www.google.com/imgres?imgurl=https%3A%2F%2Fstatic.wikia.nocookie.net%2Fnaruto%2Fimages%2Fd%2Fd6%2FNaruto_Part_I.png%2Frevision%2Flatest%3Fcb%3D20210223094656&imgrefurl=https%3A%2F%2Fnaruto.fandom.com%2Fwiki%2FNaruto_Uzumaki&tbnid=8EoJhgCyc-eLmM&vet=12ahUKEwiqtLyektv2AhX7yaACHVQOB34QMygBegUIARDVAQ..i&docid=WdjV5wKAFZeaKM&w=1440&h=1076&itg=1&q=naruto&hl=en&ved=2ahUKEwiqtLyektv2AhX7yaACHVQOB34QMygBegUIARDVAQ"}
]
function Main() {
return (
<>
<Header title={"Photowall"} />
<Photowall posts = {posts}/>
</>
)
}
export default Main
I have tried through url and through statis too but it doesnot work.
Photowall.jsx
import React from 'react'
import Photo from './Photo'
function Photowall(props) {
return (
<div className='photo-grid'>
{props.posts.map((post,index) => <Photo key={index} post={post}/>)}
</div>
)
}
export default Photowall
and photo.jsx -
import React from 'react'
function Photo(props) {
const post = props.post
return (
<div>
<figure className='figure'>
<img src={post.imageLink} alt={post.description}/>
</figure>
</div>
)
}
export default Photo
please checout this repo - https://github.com/mohitRana-04/Photowall
Try copy image address and then paste it in the respective place .
const posts = [
{
id:"0",
description:"Konoha green beast",
imageLink:"should be a valid image link"
},
{
id:"1",
description:"again Uchiha",
imageLink:"should be valid image link"
},
{
id:"2",
description:"rasenshuriken",
imageLink:"should be a valid image link"}
]
The link you are passing is not a link to an Image instead it is a url to a page,
to get an Image link you have to right click and select Open image in new tab
and after that you will see this url which is an actual link to image
http://pm1.narvii.com/6439/ecfa73c34db4039a4dd92481ea16a180a18608ed_00.jpg
and this is an actual image link because it will have an extension of image at the end
I hope this will solve your problem :)
I have a map that displays data from an array in another jsx file.
{data.map((nftDetail) => {
return (
<div className="card" key={nftDetail.id}>
<img src={nftDetail.img} alt="" />
<h3>{nftDetail.title}</h3>
<h4>{nftDetail.owner}</h4>
<h5>{nftDetail.category}</h5>
</div>
);
})}
Data example :
{
id: 1,
title: "#247",
category: "Top",
owner:"c568c3",
img:"../../assets/1.png"
},
The image is not appearing (everything else is displayed)
Screenshot
Do i need to import something else? Why is the photo not appearing? Thanks!
./1.png - does this path contain the image can you check that and use a correct path reference for the image
I've been trying to learn React over the past few weeks, and have decided to go through the LamaDev tutorial series. Yesterday I started with the portfolio tutorial (https://www.youtube.com/watch?v=hQjlM-8C4Ps&t=2798s) but have been stuck with trying to load images in my array.
I went ahead and built a component called 'Product' which the code can be found below. After that I followed the instructions and built the ProductList component which is suppose to show each of my products that are in my data.js file. I have gone and posted those below.
The problem I am running in to is that if I use a random img link from the internet the image gets imported into my product and show through my product list. However this is not what I am wanting to do since there are some images of my own I wanted to use.
When my Product.jsx tried to use a image I have saved in src/assets/img/ the img won't load. I tried using the require tag but it still is not working. I have also gone ahead and uploaded everything to my github page which can be found here and used as a reference.
I'm really not sure what I've done wrong here since everything looks right, but still know the issue is falling between the keyboard and the chair.
Thanks for any help
Product.jsx
import "./product.css";
const Product = ({ img, link }) => {
return (
<div className="p">
<div className="p-browser">
<div className="p-circle"></div>
<div className="p-circle"></div>
<div className="p-circle"></div>
</div>
<a href={link} target="_blank" rel="noreferrer">
<img src={img} alt="" className="p-img" />
</a>
</div>
);
};
export default Product;
ProductList.jsx
import Product from "../product/Product";
import "./productList.css";
import { products } from "../../data";
const ProductList = () => {
return (
<div className="pl">
<div className="pl-texts">
<h1 className="pl-title">Create & inspire. It's Jon</h1>
<p className="pl-desc">
Jon Snow is a creative portfolio that your work has been waiting for.
Beautiful homes, stunning portfolio styles & a whole lot more awaits
inside.
</p>
</div>
<div className="pl-list">
{products.map((item) => (
// console.log(item)
<Product key={item.id} img={item.img} link={item.link} />
))}
</div>
</div>
);
};
export default ProductList;
data.js
export const products = [
{
id: 1,
img: require("./assets/img/theBestTestSite.jpg"),
link: "http://google.com",
},
{
id: 2,
img: require("./assets/img/theBestTestSite.jpg"),
link: "http://google.com",
},
{
id: 3,
img: require("./assets/img/theBestTestSite.jpg"),
link: "http://google.com",
},
];
In data.js try to import images first instead of require
import img1 from "./assets/img/theBestTestSite.jpg"
export const products = [
{
id: 1,
img: img1,
link: "http://google.com",
},
// and same for others
];
I have been stucked with this for a while. I am trying to display a few component with each click, using the same button. I have tried to work around this by creating a counter so that i can keep track of the number and v-if="this.count == 3" for the component i want to show upon clicking. However, i would want one of the component to stay and displayed and not disappear the moment the v-if becomes falsy. Is there any way that i can make the component stick after its first initialize?
The sample code is as per below;
Component to display (pls ignore the data part. Tried to change the inline style display to inline-block and unsuccessful as well.
<template>
<div class="thought-box" v-if="this.count == 3">
<h5>{{msg}}</h5>
<div class="rating">
<p>Rate this thought:</p>
<b-dropdown text="Please select">
<b-dropdown-item>Very Important</b-dropdown-item>
<b-dropdown-item>Quite Important</b-dropdown-item>
<b-dropdown-item>Litte Important</b-dropdown-item>
<b-dropdown-item>Not Important</b-dropdown-item>
</b-dropdown>
OK
</div>
</div>
</template>
<script>
export default {
Name: 'ThoughtBox',
props: ['msg', 'count'],
data(){
return{
activeDisplay: 'none',
num: this.count
}
},
watch: {
num(){
alert('this thing is working');
this.activeDisplay = 'inlineBlock';
}
}
}
</script>
Base component
<template>
<div class="base">
<img src="../assets/jai-normal2.png" alt="jai_normal">
<Convo :count="num" #handleIncrement="num++"/>
<img src="../assets/uma-normal2.png" alt="uma_normal">
<ThoughtBoxContainer :count="num"/>
</div>
</template>
<script>
import Convo from '../components/Convo.vue'
import ThoughtBoxContainer from '../components/ThoughtBoxContainer.vue'
export default {
name: 'Base',
components: {
Convo, ThoughtBoxContainer
},
data(){
return {
num: 0
};
}
}
</script>
Components being reused with different props
<template>
<div class="thought-box-container">
<ThoughtBox msg="Mamak and teh tarik are quick food." :count="this.count"/>
<ThoughtBox msg="I'm still a kinda-fit footballer" :count="this.count"/>
<ThoughtBox msg="Dr. Michelle thinks I have pre-hypertension"/>
<ThoughtBox msg="I'm not sure when I have time to take care of myself"/>
<ThoughtBox msg="Gaining weight is natural with age"/>
<ThoughtBox msg="I don't want my wife to worry about my health"/>
<ThoughtBox msg="It's hard to change old habits"/>
<ThoughtBox msg="I'm embarassed to demonstrate football drills."/>
<ThoughtBox msg="My wife thinks I'm sexy when I'm fit."/>
<ThoughtBox msg="I have to work long hours for my family's future."/>
<ThoughtBox msg="I want to be in good shape to teach my kids."/>
<ThoughtBox msg="I can learn skills to keep me motivated to change"/>
</div>
</template>
<script>
import ThoughtBox from "../components/ThoughtBox.vue"
export default {
Name: 'ThoughtBoxContainer',
components: {
ThoughtBox
},
props: ["count","msg"]
}
</script>
Code is a bit messy cause i'm a newbie. If you have any suggestions to refactor the code, im all ears to listen and learn.
Thank you!
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:)