Scrolling element scrollbar jumping to top after re-render - javascript

I'm using Gatsby and i made a vertical side navigation menu. I used useRef for navigation wrapper and for every item inside menu for getting some height values. Then I calculated the scroll position for active navigation link as you can see below and set scrollTop value for navigation wrapper and i can align scroll bar to active link item.
function calculateScrollPosition(wrapper, link) {
const distance = wrapper.current.scrollHeight - wrapper.current.offsetHeight
const scrollUnit = wrapper.current.scrollHeight / distance
const itemOffset =
wrapper.current.scrollHeight / 2 < link.current.offsetTop
? link.current.offsetTop + link.current.clientHeight
: link.current.offsetTop - link.current.clientHeight
const position = Math.floor(itemOffset / scrollUnit)
wrapper.current.scrollTop = position
}
and i am calling it here
useEffect(() => {
if (activeLink) {
calculateScrollPosition(list, activeLink)
}
}, [activeLink])
But each time I click the link inside sidebar and change the page, scrollbar of navigation jumping to top for a second and then finding the right place. I expect it to go to new position from last position, not jumping to top. Any help i will appreciated.

Thank you for your comments. I actually fixed my problem so i want to explain how i did.
As i mentioned, I'm using Gatsby and i have multi-lang website. Pages creating dynamically with .md files. Gatsby re-renders when the top level component changes between pages. Actually that was broke my sidebar transitions too because it was unmount and mount layout again when i change page.
Gatsby doesn't automatically wrap pages in a layout component. So I wrapped pages with layout using gatsby-plugin-layout. I made 2 different layout. One of it main layout with sidebar and header, other one for my dynamically created pages. I can use one of inside another. Now its not re-render my main layout, it is just re-render layout which i created for pages inside main layout, scrollbar not jumping to top and transitions are works fine.
I don't know if i explained well. I hope it helps others who have the same problem.

Related

How to move vertical scroll dynamically in Material UI DataGrid component[React]

I am using Material UI DataGrid component in my project.
(components info : https://material-ui.com/api/data-grid/data-grid/)
But, I can't move the vertical scroll to selected row position like this.
const windows = document.getElementsByClassName('MuiDataGrid-window')[0];
windows[0].scrollTop = 10; // 10 is for test.
I find that the div tag which has class name called 'MuiDataGrid-window' has vertical scrollbar.
So. I tried that.. It doesn't work.
Does anyone know about this info?

Header flickering and freezing issue with material table (implemented with react window + react window infinite loader)

I have implemented an Infinite scrolling table with react-window (based on #60) and material UI.
The table seems to be fulfilling the main objective but there are few issues with it -
header is not sticking on the top in spite of having styles in place (stickyHeader prop).
header is flashing/flickering while scrolling quickly towards up direction.
[Steps to reproduce - scroll 50% down then do fast scroll up and observe the header movement ].
Here's the codesandbox example - https://codesandbox.io/s/react-window-with-table-elements-forked-huti6?file=/src/index.tsx:514-542
Use default value for TableContainer overflow-x and the sticky header should work
import { makeStyles } from '#material-ui/core/styles'
const useStyles = makeStyles({
tableContainer: {
overflowX: "initial"
}
})
function Inner({ children, ...rest }, ref) {
const { header, footer, top } = useContext(VirtualTableContext)
const classes = useStyles();
return (
<TableContainer classes={{root: classes.tableContainer}} {...rest} ref={ref}>
...
As an alternative to your implementation, the Material UI docs have a working example of a virtualized table which achieves what you're looking for using react-virtualized. That is, the header is sticky and there is no flashing/flickering of the header during scroll.
Below is a codesandbox
containing a working example to reflect your desired layout.
First about the react-window: The Scollbars in the react-window are for the outercontainer not for InnerContainer. Now don't try to replace the outer container itself, unless you want to handle everything yourself. All the scroll events a few more things are attached to the outercontainer.
Think of it like outer container decides/takes the size and the larger inner container gets scrolled inside it.
Now looking at your case I assume you are trying to make the table behave like any other grid where headers are fixed and content is scrolled if it's getting overflow. your table header is way lower in the element hierarchy than the inner container, so no way you can write any simple css (or js logic) to achieve in current hierarchy.
that's why even though you have set the stickyheader for the MaterialUI table, it won't stick. Cause your whole table (MaterialUI table) is getting scrolled inside the outer container of react-window.
I would suggest you to move your table header outside of the react-window and only place the rows in the react-widow. that's the way it's suppose to behave (i.e. react window treats everything in it as scrollable content). See one of the presentation below:
A little tip on redesigning of your table (guess the alignment can be improved by additional css)

Using Parent Scrollbar instead of Sub Component Scrollbar with Angular Virtual Scroll

Context
I'm using angular virtual scroll to display a long list of elements. My design is very simple and can be seen in the image below.
Current Behaviour
Currently, the virtual scroll has its own scrollbar which operates differently from the parent scroll bar. This makes it very tedious to scroll to the footer. i.e. When you scroll to the end of the list it does not scroll to the footer.
Desired Behaviour
I want the virtual scroll container to use the parent scroll bar instead of its own such that when the end of the list is reached, regular scrolling is resumed.
A Stackblitz can be found here illustrating the undesired behaviour: https://stackblitz.com/angular/aemdyrjmebn
This is default scrolling behavior native to the browser (I tried it on Chrome). For example the same thing will happen with the overflow: scroll example on MDN: after the container has been fully scrolled down, the scrolling of the parent/window will not begin until the mouse is moved. This is also what happens with Angular Virtual Scrolling
If there is another way to achieve what you're looking for you would need to do it when the virtual container has been scrolled to the bottom - and you can get this event with the following code:
#ViewChild(CdkVirtualScrollViewport, {static: false}) virtualScroll: CdkVirtualScrollViewport;
ngAfterViewInit() {
this.virtualScroll.elementScrolled().pipe(
filter(event => {
return this.virtualScroll.measureScrollOffset('bottom') === 0;
}),
tap((event)=> {
// do something here
})
).subscribe()
}

Trouble Resizing Both Panes in react-split-pane

I have a horizontally split pane for one of my projects in React.js. I'm using react-split-pane to handle the resize logic. Each pane contains a table wrapped in a few other components.
The issue I'm having is getting the bottom pane to adjust its size to the leftover space within SplitPane. For example, if the total height of the container is 1000px and the top pane gets resized to 300px, I need the bottom pane to be 700px. I was able to resize the bottom pane to the same size of the top pane. How can I get the bottom pane to resize to the leftover space of the total container?
I have a simplified recreation of the problem in a Sandbox here
The second problem I'm having is that when I do resize with this new logic in place, it looks very choppy and lags quite a bit. You can't tell in the Sandbox, but in the actual project, it gets pretty bad. Is there a better way to solve this problem that makes the resizing more fluid? If so, how can I achieve this?
Thanks!
Is this what you are trying to achieve? Sandbox
I just added some logic in your toggleBtmHeight function to find out what the height of the bottom pane should be after resizing. When you resize the pane, the onChange callback passes you the height of the primary (top) pane. You need to use maxHeight - topPaneHeight = bottomPaneHeight to figure out what the height of the bottom pane should be:
toggleBtmHeight(topPaneHeight) {
const maxHeight = 1000;
const padding = 225;
const btmPaneHeight = maxHeight - topPaneHeight - padding;
this.setState({ btmHeight: btmPaneHeight + "px" });
}
As far as how to handle the choppiness, it's hard to say without seeing it in the full context of your app, but I would guess that when you update state it's re-rendering a bunch of components causing the lag. I would look into adding shouldComponentUpdate to your components to help manage when they should actually be re-rendered.

How to handle only scroll on child DOM element instead of body element?

I am using the code below for scrolling to the element on a button click event.
Here is the code :
this.scrollTo = function(id) {
var old = $location.hash();
$location.hash(id);
$anchorScroll();
$location.hash(old);
};
With the above code, scroll is working fine. But actually my html page is having two scroll bars one is the default at page level and the other is at sub DOM element level. When the above code executes, its moving both the scroll bars and due to that its not visible correctly.
How can i restrict the default scroll bar and allow only the child/sub scroll bar to handle to scroll event ?
Please look into the below example in Chrome Browser:
plnkr.co/edit/pXwnjjh3VxCnhTHwd0tJ?p=preview
Actually I am facing the problem when I use navigation/top bar. There could be multiple ways to solve the problem by applying CSS styles.
I solved my problem by removing child scroll bar and using the below method:
window.scrollTo(0, element.offset().top - 120);
Instead of
$anchorScroll();

Categories