'React Bootstrap scroll down to content after accordion is opened
I have a react bootstrap table column accordion that has content in it. I am facing the issue is if panel opens user unable to identify the content until scroll down.
I wanted to be able to scroll down to the content when accordion collapse is opened.
This is what my parent function component looks like,
import React, {forwardRef, useContext} from "react";
import AccordionContext from "react-bootstrap/AccordionContext";
import { Table } from "react-bootstrap";
function CustomToggle({ children, eventKey, callback, className }) {
const currentEventKey = useContext(AccordionContext);
const decoratedOnClick = useAccordionToggle(
eventKey,
() => {
let eventType = `${currentEventKey ? 'close' : 'open'}`;
callback && callback(eventKey,eventType)
},
);
return (
<tr onClick={decoratedOnClick}>
<td><Image src={"accordion_arrow_down.svg"} /></td>
</tr>
)
}
function ParentComponent()
{
const scrollDownRef = React.useRef(null);
const toggleHandle = (eventKey,eventType) => {
if(scrollDownRef && scrollDownRef.current) {
scrollDownRef.current.scrollIntoView({
behavior: "smooth",
block: "nearest",
inline: "start"
});
}
}
return (
<div>
<Table>
<tbody>
<CustomToggle callback={toggleHandle} eventKey={{}} />
<tr>
<td>
<Accordion.Collapse eventKey={{}}>
<ChildComponent ref={scrollDownRef} />
</Accordion.Collapse>
</td>
</tr>
</tbody>
</Table>
</div>
)
}
and child component looks like below,
function ChildComponent({ref}) {
return (
<div>
<Form>
<div ref={ref}>
</div>
</Form>
</div>
)
}
export default forwardRef(ChildComponent)
I have also tried with setTimeout function as well, if the ref element has to be identified if there is any delay with the accordion open time. Nothing worked here.
I have tried other scroll methods in the place of scrollIntoView funtion. But neither do anything to the page.
Any help would be appreciated!
Solution 1:[1]
I have tried to use your code but it contains many errors here and there. So I have created a simple example that you can use.
In App.js
import React, { useState, forwardRef, useRef } from "react";
import { Accordion, Table, Card, Container } from "react-bootstrap";
const ChildComponent = forwardRef((props, ref) => {
return (
<div>
<Accordion.Collapse eventKey="0" className="border">
<Card.Body
style={{ height: "calc(100vh + 200px)" }}
className="d-flex align-items-end justify-content-center"
>
<Container>
<div ref={ref}> Some Content. Lorem Ipsum. Hello World.</div>
</Container>
</Card.Body>
</Accordion.Collapse>
</div>
);
});
const App = () => {
const [activeEventKey, setActiveEventKey] = useState("");
const accordElem = useRef(null);
const handleClickToggle = (eventKey) => {
if (eventKey === activeEventKey) {
setActiveEventKey("");
} else {
setActiveEventKey(eventKey);
//Handle Scroll here when opening
setTimeout(() => {
accordElem.current.scrollIntoView({
behavior: "smooth",
block: "end",
inline: "nearest",
});
}, 400);
}
};
return (
<div>
<Accordion activeKey={activeEventKey}>
<Table>
<tbody>
<tr>
<Accordion.Toggle
as="td"
eventKey="0"
onClick={() => handleClickToggle("0")}
>
Add Mock
</Accordion.Toggle>
</tr>
<tr>
<td>
<ChildComponent ref={accordElem} />
</td>
</tr>
</tbody>
</Table>
</Accordion>
</div>
);
};
export default App;
Explanation:
- I used Card, Container components for the purpose of demonstration. I added some styles as well to make sure accordion content is taller than my screen size so scrolling can be seen
- Instead of Custom Toggle, you can use Accordion.Toggle and give the value as='td' for it to be used as a element.
- You can use setTimeout so that component is rendered and ref is not null
Here is a CodeSandbox link with example : https://codesandbox.io/s/festive-sun-o0e4ih
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Surya K |
