split slider Items in multiple rows - javascript

I hope you can give me a hint:
A slider of category images with a url link will be displayed on a start page. Just 4 images per row have to be displayed. How can do that? I cant see the solution. :-/
The website uses i.a. react.js.
<div className="middle-section">
{categories && categories.length > 0 &&
<div className="categories-wrapper">
<Slider multi>
{
categories.map((model) => {
return <CategoryItem key={model.ID} model={model}
url={urlGenerator.get({ page: 'category', id: model.FriendlyID, name: decodeStringForURL(model.Name) })} />
}
)
}
</Slider>
</div>
}
The element CategoryItem looks like below:
const CategoryItem = ({ model, url, className }) => {
if (!model) {
return <div className="category-item" />
}
const imageUrl = model.ImageUrl ? model.ImageUrl : require(`$assets/images/default.png`)
return (
<div>
<Link to={url}>
<a className={`category-item ${className || ''}`} data-qaautomationinfo={model.FriendlyID}>
<div className="image-wrapper">
<img src={imageUrl} />
</div>
<div className="category-name">
<HTMLLinesEllipsis style={{ whiteSpace: 'pre-wrap' }} unsafeHTML={model.Name} maxLine={2} basedOn='words' />
</div>
</a>
</Link>
</div>
)
}
The CSS of CategoryItem looks like below:
.category-item {
display: flex;
flex-direction: column;
font-size: var(--text-size-label);
}
I really cant see it.
Hope you can help me guys.
Thx a lot!

Related

I am trying to align movieCards side by side. But they are aligning in a column

This is my movie list component. I tried different attributes in the div section to get the cards in a row. But all the cards are aligned in a column.should i use either flex or grid.If yes how can i use them. Even i referred to many resources for this.But didn't worked for me. What should I do to get the cards as I wish . Please assist me.
import React, { useState } from 'react'
import { useSelector } from 'react-redux'
import MovieCard from './MovieCard'
const MoviesList = (props) => {
const [search, setSearch] = useState('')
const [filterBy, setFilterBy] = useState([])
const [orderBy, setOrderBy] = useState('')
const movies = useSelector((state) => {
console.log(state.movies)
return state.movies
})
const handleChange = (e) => {
const inputValue = e.target.value
setSearch(inputValue)
const filteredValue = movies.filter((movie) => {
return movie.Title.toLowerCase().includes(inputValue)
})
setFilterBy(filteredValue)
console.log(filteredValue)
}
const handleSelectChange = (e) => {
setOrderBy(e.target.value)
}
const show = (movies) => {
switch (orderBy) {
case 'a-z': return [...movies.sort((a, b) => a.Title.localeCompare(b.Title))]
case 'z-a': return [...movies.sort((a, b) => b.Title.localeCompare(a.Title))]
case '1-100': return [...movies.sort((a, b) => a.imdbRating - b.imdbRating)]
case '100-1': return [...movies.sort((a, b) => b.imdbRating - a.imdbRating)]
default: return [...movies]
}
}
return (
<div className='container'>
<div className='d-flex mb-3 '>
<h1 style={{ textAlign: 'center', border: 'solid lightgreen', backgroundColor: 'white' }} >My Movie List</h1>
<form style={{ float: 'right', marginRight: '35px' }}>
<input type="text" placeholder='search by name' value={search} onChange={handleChange} />
<select value={orderBy} onChange={handleSelectChange} >
<option value="">orderBy</option>
<option value="a-z">a-z</option>
<option value="z-a">z-a</option>
<option value="1-100">1-100</option>
<option value="100-1">100-1</option>
</select>
</form>
</div>
<div className=" row pt-2 justify-content-around " style={{ textAlign: 'center', width: '100%' }}>
{
filterBy.length > 0 ? (
filterBy.map((movie) => {
return <MovieCard key={movie.imdbID} Poster={movie.Poster} Title={movie.Title} imdbRating={movie.imdbRating} imdbID={movie.imdbID} />
})
) : (
show(movies).map((movie) => {
return <MovieCard key={movie.imdbID} {...movie} />
})
)
}
</div>
</div >
)
}
export default MoviesList
And this is Movie card component
import React from 'react'
import { useDispatch } from 'react-redux'
import { removeMovie } from '../actions/moviesAction'
const MovieCard = (props) => {
console.log(props)
const { Title, Poster, imdbRating, imdbID } = props
const dispatch = useDispatch()
return (
<div className="card mt-2 p-2 bd-highlight border shadow rounded" style={{ width: '16rem' }}>
<img className="card-img-left pt-2" src={Poster} alt={Title} style={{ width: '200px', height: '200px' }} />
<div className="card-body">
<h4 className="card-title">Name : {Title}</h4>
<h5 className="card-title">Ranking : #{imdbRating}</h5>
<ion-icon name="trash" style={{ color: 'red' }} onClick={() => {
dispatch(removeMovie(imdbID))
}}>
</ion-icon>
</div>
</div>
)}
export default MovieCard
Please help me to resolve this. Thankyou
Try providing display: flex, to the div rendering MovieCard, like this:
<div className=" row pt-2 justify-content-around "
style={{ textAlign: 'center', width: '100%', display: 'flex' }}>
{
filterBy.length > 0 ? (
filterBy.map((movie) => {
return <MovieCard key={movie.imdbID} Poster={movie.Poster} Title={movie.Title} imdbRating={movie.imdbRating} imdbID={movie.imdbID} />
})
) : (
show(movies).map((movie) => {
return <MovieCard key={movie.imdbID} {...movie} />
})
)
}
</div>
You can just use flex here.
add the below code to your parent div (div containing all the cards).
If you have a css file add a class to that div and add the following styles.
display: flex;
flex-wrap: wrap;
justify-content: center;
or if you want to use inline styling do the following:
<div className=" row pt-2 justify-content-around " style={{ textAlign: 'center', width: '100%', display: "flex", flexWrap: "wrap", justifyContent: "center" }}>
{filterBy.length > 0 ? (
filterBy.map((movie) => {
return <MovieCard key={movie.imdbID} Poster={movie.Poster} Title={movie.Title} imdbRating={movie.imdbRating} imdbID={movie.imdbID} />
})
) : (
show(movies).map((movie) => {
return <MovieCard key={movie.imdbID} {...movie} />
}
)
)}
</div>
Try using a grid method something like the code below will allow you control the number of rows and columns you want as well as size them.
**
<h1>Example { grid-template-rows: 40% 50% 50px;}</h1>
<p><strong style="color: red">The shorthand property, grid-template, can replace both </strong>grid-template-rows and grid-template-columns.</p>
<hr>
<p style="font-family: Courier">When using grid-template, the values before the slash will determine the size of each row. The values after the slash determine the size of each column. </p><hr>
<p style="font-family: Courier">In this example there are 3 rows and 3 columns added to the grid.</p><h1>Example {grid-template: 40% 50% 50px/100px 50% 200px;}</h1><br>
<p><strong style="color: red">By using the (fr) unit, we can define the size of columns and rows as a fraction of the grid’s length and width.</strong><br>Using (fr) makes it easier to prevent grid items from overflowing the boundaries of the grid.</p>
<h1>Example {grid-template: 1fr 1fr 1fr / 3fr 50% 1fr;}<br> width: 400px;<br>
**
If you're using Bootstrap then you don't need to use flex nor grid directly. This is the Bootstrap's way to achieve the desired layout:
<div className="row">
{movies.map(item => (
<div className="col">
// then here yo can put your card for the movie
</div>
))}
</div>
This is the Bootstrap doc about it

React Recharts: Design custom tooltip

I am trying to replace recharts default tooltip with custom tooltip.
The existing tooltip looks like this.
I wanted to replace the above default tooltip as
I made sandbox for the code.
Thanks
Very quick solution. You can alter it as you want
Create a custom tooltip class
export const CustomTooltip = ({ active, payload, label }) => {
if (active && payload && payload.length) {
return (
<div className="custom-tooltip">
<p className="label">{`${label} : ${payload[0].value}`}</p>
<div>
{payload.map((pld) => (
<div style={{ display: "inline-block", padding: 10 }}>
<div style={{ color: pld.fill }}>{pld.value}</div>
<div>{pld.dataKey}</div>
</div>
))}
</div>
</div>
);
}
return null;
};
And use it like this
<Tooltip content={<CustomTooltip />} cursor={{ fill: "transparent" }} />
demo

Change src of image on hover with array property

I'm mapping through an array that contains properties such as image: link to image and hover_image: link to image
Is there a way to change an image on hover? Something sort of like this:
<img src={hover ? item.hover_image : item.image} />
If so, how can I define that the element is being hovered over, thank you!
Update: the onMouseHover or any other onMouse seems to not work on my image tag, here is the code:
{array.map((item, key) => {
<div key={key}>
<a target="_blank" href={item.link} >
<img
onMouseEnter={(e) => console.log(e.currentTarget.src)}
alt={item.name}
src={item.image}
/>
</a>
</div>
})}
React has two event handlers for that:
onMouseEnter
onMouseLeave
You could put those events on the component that you are hovering over and make them set a state variable, to track the hover state. e.g.:
function YourOuterComponent({item}) {
const [hover, setHover] = useState(null);
return (
<>
<div id='whatever'
onMouseEnter={(e) => setHover(e.currentTarget.id)}
onMouseLeave={() => setHover(null)}>
hover over me
</div>
<img src={hover ? item.hover_image : item.image} />
</>
);
}
Edit based on coments:
{array.map((item, key) => (
<div key={key}>
<a target="_blank" href={item.link}>
<img
alt={item.name}
src={item.image}
onMouseEnter={(e) => {
e.currentTarget.src = item.hover_image;
}}
onMouseLeave={(e) => {
e.currentTarget.src = item.image;
}}
/>
</a>
</div>
))}
Inline JavaScript version**
<img src="a.jpg" onmouseover="this.src='b.jpg'" onmouseout="this.src='a.jpg'" />
this refer to the current img tag
Example :
<img width="100" height="100" src="https://onlinejpgtools.com/images/examples-onlinejpgtools/coffee-resized.jpg" onmouseover="this.src='https://cdn.pixabay.com/photo/2021/08/25/20/42/field-6574455__340.jpg'" onmouseout="this.src='https://onlinejpgtools.com/images/examples-onlinejpgtools/coffee-resized.jpg'" />
You can achieve this behaviour by changing the src property of the target on which the event has occurred.
For an example:
function App() {
const imgs = [
{
image:
"https://images.unsplash.com/photo-1644982654072-0b42e6636821?ixlib=rb-1.2.1&ixid=MnwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80",
hover_image:
"https://images.unsplash.com/photo-1648655514581-12808a5eb8c3?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwzfHx8ZW58MHx8fHw%3D&auto=format&fit=crop&w=500&q=60",
},
];
const elements = imgs.map((img, i) => {
return (
<img
key={i}
onMouseOver={(e) => {
e.target.src = img.hover_image;
}}
src={img.image}
style={{ height: "200px", width: "200px" }}
/>
);
});
return <div className="app">{elements}</div>;
}

excluding missing data when mapping through JSON in React/Js

I have a React component set up to map through a JSON file of projects and display the information in a card. However some of projects have less information that others. Namely my wordpress website does not need a link to the code. However I have it set up like:
Code:
<p>{project.code}</p>
How can I change this to an if statement, saying if Code is a property then return that block of code or else do not display 'code:' at all.
Here is my two files for reference.
Projects.js:
import React from "react";
import ReactCardFlip from "react-card-flip";
import Data from "../../ProjectData.json";
import './Projects.scss'
import '../MediaQueries/Projects.scss'
const CardStyle = {
padding: "30px",
margin: "30px",
width: "250px",
height: "300px",
};
const Card = ({ project }) => {
const [isFlipped, setIsFlipped] = React.useState(false);
// console.log(project);
return (
<div className="Card-wrapper">
<ReactCardFlip isFlipped={isFlipped} flipDirection="horizontal">
<div
style={CardStyle}
onMouseEnter={() => setIsFlipped((prev) => !prev)}
className="CardFront"
>
<div className="CardFront-div1">
<h3 className="CardFront-div1-title">{project.title}</h3>
<img width="250" src={project.gif} alt="" className="CardFront-div1-gif"/>
<div className="CardFront-div1-list">
<p>{project.html}</p>
<p>{project.css}</p>
<p>{project.javascript}</p>
<p>{project.react}</p>
</div>
</div>
</div>
<div
style={CardStyle}
onMouseLeave={() => setIsFlipped((prev) => !prev)}
className="CardBack"
>
<div>
<p>{project.description}</p>
<span>
Project:
<p>{project.link}</p>
</span>
<span>
Code:
<p>{project.code}</p>
</span>
</div>
</div>
</ReactCardFlip>
<button onClick={() => setIsFlipped((prev) => !prev)} className="cardflip-button">Flip</button>
</div>
);
};
const Projects = () => {
return (
<>
<h1>Projects</h1>
<div className="Projects" id="Projects">
{Data.map((item, index) => (
<Card project={item} key={`card-${index}`} />
))}
</div>
</>
);
};
export default Projects;
{
project.code ? (
<span>
Code:
<p>{project.code}</p>
</span>
) : null
}
Post got deleted by the user but the code is what I was looking for:
{!!project.code && (
<span >
Code:
<p>{project.code}</p>
</span>
)}

React bind function to each item inside array

I'm trying to make it so when you click on the dropdown arrow the settings dropdown will appear.
When I currently press an arrow dropdown, all the settings dropdown open that are within the array loop.
This is the function that renders the loop:
viewPublishedPages() {
const pages = this.state.pages;
return (
<div>
{pages.map((val, i) => {
let dropdown = 'none';
return (
<div className="block" key={i}>
<div className="columns">
<div className="column is-10">
<p>PUBLISHED</p>
<h2>{val.title}</h2>
</div>
<div className="column">
<div className="settings">
<div className="arrow__container">
<div className="arrow" onClick={this.showSettings.bind(this, i)} />
</div>
{
this.state.settingPanel
?
<ClickOutside onClickOutside={::this.hide}>
<div className="arrow__dropdown">
<Link href={{pathname: '/admin/edit-page', query: {title: val.title}}}>
<a className="arrow__dropdown__link">Edit</a>
</Link>
<button
className="arrow__dropdown__delete"
onClick={() => this.handleDelete(i)}>Delete</button>
</div>
</ClickOutside>
: null
}
</div>
</div>
</div>
</div>
);
})}
</div>
);
}
Notice: <div className="arrow" onClick={this.showSettings.bind(this, i)} />
This is the state:
static dataStruc () {
return {
loading: true,
settingPanel: false,
pages: [],
};
}
Your are currently saving a boolean value to settingPanel and therefore all dropdowns open upon click.
My suggestion is replace settingPanel from boolean to the respective page id. In case you don't have page ids, then store the current page index on it.
That makes it easier to render the dropdown so you have access/control to the selected one and later render its settings:
showSettings(index) {
this.setState({
settingPanel: index,
})
}
And then in viewPublishedPages:
{this.state.settingPanel === i &&
<ClickOutside onClickOutside={::this.hide}>
..
</ClickOutside>}
I wrote a sample code so you get the idea.
class App extends React.Component {
constructor() {
super()
this.state = {
pages: [
{ title: 'Home' },
{ title: 'Contact' },
{ title: 'Page' }
],
settingPanel: -1,
}
this.showSettings = this.showSettings.bind(this)
}
showSettings(index) {
this.setState({
settingPanel: this.state.settingPanel === index ? -1 : index,
})
}
render() {
const { pages, settingPanel } = this.state
return (
<div>
{pages.map((page, index) =>
<div key={index} className="page">
<div onClick={this.showSettings.bind(this, index)}>
{page.title}
</div>
{settingPanel === index &&
<div className="settings">
<div>Setting 1</div>
<div>Setting 2</div>
<div>Setting 3</div>
</div>
}
</div>
)}
</div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
)
.page {
background-color: cyan;
margin-top: 10px;
padding: 10px;
}
.settings {
background-color: black;
color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

Categories

Resources