I have a array of 20 items
. In UI, I have two buttons and the 20 items. My UI looks like this.
When Clicking the Prev
and Next
Buttons, it scrolls correctly.
But now my need was.
When the div
block reaches 1st item
, i want to hide the prev
button and show only Next
button. Same as like when i reach last 20th item
, i want to hide next
button and show only Prev
Button. In between div
, i want to show two buttons.
I tried but don't know how to achieve it. Please Help with some soltions.
Here's the Code i tried:
import { useRef } from "react";
export default function App() {
const cardsContainerRef = useRef();
const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
const onPrevorNextBtnClick = (scrollOffset) => {
cardsContainerRef.current.scrollLeft = scrollOffset;
};
return (
<div>
<div style={{ display: "flex", gap: "10px" }}>
<button
onClick={() => {
onPrevorNextBtnClick(-300);
}}
>
Prev
</button>
<div
ref={cardsContainerRef}
style={{ display: "flex", gap: "10px", overflow: "hidden" }}
>
{data.map((item, index) => (
<div
style={{
width: "100px",
height: "100px",
flexShrink: 0,
backgroundColor: "green",
color: "white"
}}
>
{item}
</div>
))}
</div>
<button
onClick={() => {
onPrevorNextBtnClick(300);
}}
>
Next
</button>
</div>
</div>
);
}
CodePudding user response:
You can use Intersection Observer (IO) for this. With IO you can observe an element and react whenever it comes into view (or leaves the view)
So you set up IO on your first and last element and whenever they are entering or leaving the view you add / remove a class that shows or hides the button.
I created a basic snippet where you can see the approach. You will have to add your logic to show / hide the buttons accordingly. I also only log when element is becoming visible, if you want to react for when it comes out of the view you have to add this too to the callback function.
let options = {
root: document.querySelector('ul'),
threshold: 0.9
}
let callback = (entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
console.log(`${entry.target.className} is intersecting`);
}
});
};
let observer = new IntersectionObserver(callback, options);
let targets = document.querySelectorAll('li:first-child, li:last-child');
targets.forEach(target => {
observer.observe(target);
})
* {
padding: 0;
margin: 0;
}
ul {
display: flex;
overflow: auto;
max-width: 400px;
gap: 10px;
}
li {
list-style-type: none;
flex: 200px;
min-width: 200px;
height: 150px;
background: #b00b15;
}
<ul>
<li >
Test
</li>
<li>
Test
</li>
<li>
Test
</li>
<li >
Test
</li>
</ul>
CodePudding user response:
for the next button you can add a condition on it to be hidden when you are at [data.length -1] .
for the the previous button you can add a condtion on it to be hidden when you are not at data[0]
here my example and it's work for me :
<button type="button" (click)="carrouselPrevAction()"
*ngIf="!carrouselItems[0].active && carrouselItems.length> carrouselCards">
</button>
<button type="button" (click)="carrouselNextAction()"
*ngIf="!carrouselItems[carrouselItems.length - 1].active && carrouselItems.length> carrouselCards">
</button>
carrouselPrevAction() {
const index = this.carrouselItems.findIndex((element: any) => element.active == true)
this.carrouselItems[index - 1].active = true;
this.carrouselItems[index this.carrouselCards - 1].active = false;
}
carrouselNextAction() {
const index = this.carrouselItems.findIndex((element: any) => element.active == true)
this.carrouselItems[index].active = false;
this.carrouselItems[index this.carrouselCards].active = true;
}