I have a modal with a long form in my react application. So when I submit the form I am showing the validation messages from the server on top of the form. So the user has to scroll to the top to view the messages. So I want to automatically scroll to the top when the message appears. So I added the below code in the submit handler function. But it is not working.
setAddModalErrorMsg([{ msg: res.data.msg, type: "error" }])
window.scrollTo({
top: 0,
left: 0,
behavior: "smooth"
});
The other answers showed how you can scroll the modal to the top, and that is the generally accepted way of achieving this, though, I want to show you how to scroll the "Message" into view, regardless of whether it's on the top or not.
You would also need to create a ref to where you display your message and use the scrollIntoView functionality to scroll the modal to your validation message.
import React, { useRef } from 'react';
const Modal = () => {
const validationMessageRef = useRef();
const setAddModalErrorMsg = () => {
// scrolls the validation message into view, and the block: 'nearest' ensures it scrolls the modal and not the window
validationMessageRef.current?.scrollIntoView({ block:'nearest' });
}
return (
<div>
<div ref={validationMessageRef}>
// your validation message is displayed here
</div>
// rest of your modal content here
</div>
)
}
to automatically scroll to the top we can use the below code :
constructor(props) {
super(props)
this.myRef = React.createRef() // Create a ref object
}
add the scrollTo function after setAddModalErrorMsg.
setAddModalErrorMsg([{ msg: res.data.msg, type: "error" }])
this.myRef.current.scrollTo(0, 0);
<div ref={this.myRef}></div>
attach the ref property to a top dom element
You're trying to scroll window, but chances are your window is already at the top, it's your modal element that needs to scroll up.
To do this, i'd create a reference to the modal element, then in your function scroll the modal element via the ref, so something along the lines of:
import React, {useRef} from 'react';
const Modal = (props) => {
// use the useRef hook to store a reference to the element
const modalRef = useRef();
const setAddModalErrorMsg = () => {
// check the ref exists (it should always exist, it's declared in the JSX below), and call a regular javascript scrollTo function on it
modalRef.current?.scrollTo({x: 0, y: 0, animated: false});
}
// see here we create a reference to the div that needs scrolled
return (
<div ref={modalRef}>
{ // your modal content }
</div>
)
}
Related
Hello I am using a react library called "react-intersection-observer"
and have it set like
const { ref: myRef, inView: myElementIsVisible } = useInView();
when I scroll to this element
<div ref={myRef} onChange={myElementIsVisible && handleSetPage}>
Hello
</div>
myElementIsVisible will be set to true from false,
however I want it to trigger the function handleSetPage when user scrolls to this element (when myElementIsVisible = true)
how can I achieve that?
I hope that after I input a new message, the window can instantly move to the bottom of the blue block to see the latest message!
After trying for a long time, I haven't realized it. I would like to ask you what can you do to achieve this effect?
thank you all.
example
Put a template ref on the chat window:
<template>
<div class="chat" ref="chatWindow">
...
</div>
</template>
That lets you access the chat window in <script> with this.$refs.chatWindow.
In sendmessage(), set the chat window's scrollTop to scrollHeight in the next tick (after the new message is rendered in the chat list):
export default {
methods: {
sendmessage() {
this.paragraph.push({
content: this.message
})
this.message = ''
this.$nextTick(() => {
this.$refs.chatWindow.scrollTop = this.$refs.chatWindow.scrollHeight
})
}
}
}
demo
I am designing the registration page in Reactjs .and I am doing manual validation. now what I want is after clicking onSubmit, the page should scroll to the top to show all errors in the validation.I tried but failed to achieve this.is there anyone who will help me
This line of code works for me
window.scrollTo(0, 0);
If you task is to scroll to errors rather than scrolling to top, you can try this.
import React { useRef } from 'react';
const Component = () => {
const errorRef = useRef(null);
const onSubmitHandler = () => {
...
errorRef.current.scrollIntoView();
}
return (
...
<div ref={errorRef} className='error-container'>
...
</div>
...
);
}
Note: Still you want to try scroll to top you can try this.
window.scrollTo(0,0);
or
window.scrollTo({
top: 0,
left: 0,
behavior: 'smooth'
});
Am currently using framework7 and I have this problem wherein I need to get a button floating once the user pass scrolling a specific element.
But for some reason am not able to make the scroll event work. Even used a native event listener but still no luck.
Here is my code. In my component:
export default {
methods: {
handleScroll(event) {
alert('should work')
}
},
created() {
window.addEventListener('scroll', this.handleScroll);
},
destroyed() {
window.removeEventListener('scroll', this.handleScroll);
},
mounted() {
window.addEventListener('scroll', this.handleScroll)
this.handleScroll;
var element = document.querySelector(".similar-adventures");
var top = element.offsetTop;
window.scrollTo(0, top);
}
}
And here is my native event listener code:
window.addEventListener(‘scroll’, function(e){
// Get the new Value
newValue = window.pageYOffset;
//Subtract the two and conclude
if(oldValue - newValue < 0){
console.log(“Up”);
} else if(oldValue - newValue > 0){
console.log(“Down”);
}
// Update the old value
oldValue = newValue;
});
I know this is old now but i will answer for future reference, so i think the problem here is that the window is not actually scrolling as framework7 uses pages/views.
In vue the renders to 2 divs like so..
<f7-page>
<div slot="fixed">Fixed element</div>
<p>Page content goes here</p>
</f7-page>
<!-- Renders to: -->
<div class="page">
<div>Fixed element</div>
<div class="page-content">
<p>Page content goes here</p>
</div>
</div>
i found that its the page-content class that you want to put the eventListenter on best way to do this is Dom7 like so...
let page = $$('.page-content')
page.on('scroll', () => {
console.log(page.scrollTop()) // will show page top position
page.scrollTop(0) // will scroll to top
})
//if you have multiple pages
let page = $$('.page-content')
let home = $$(page[0])
let about = $$(page[1])
page.on('scroll', () => {
console.log(home.scrollTop()) //home page top position
console.log(about.scrollTop()) //about page top position
})
//more options
page.scrollTop(position, duration, callback)
page.scrollTo(left, top, duration, callback)
just remember to import $$ from 'Dom7'
This code retrieves all the pages from the f7 component in an array
let pages = document.querySelectorAll('.page-content');
Then to make a page scrollable, select the respective index and do:
pages[0].addEventListener('scroll', function () { console.log('is scrolling...') } );
For the same code but in a more beautiful way as we don't want to specify the page by index:
add an id to your f7-page tag
<f7-page name="whatever" id='myPage'>
then do this code for example in mounted:
let f7page = document.getElementById('myPage');
let scrollableDiv = f7page.querySelector('.page-content');
scrollableDiv.addEventListener('scroll', function () { console.log('is scrolling...') } );
special thanks to BiscuitmanZ's comment for finding the underlying issue
I have the below react component which is essentially a chat-box
render(){
const messages = this.props.messages;
return(
<div id="project_chat">
<h1>{this.props.project[0].project}</h1>
<div className="chat_room">
<div className="messages" ref="messages">
<Waypoint onEnter={this.activateWayPoint}/>
<ul>
{messages.map((message) => {
return(
<Message key={uuid.v4()} message={message}/>
)
})}
</ul>
</div>
<div className="chat_message_box">
<input type='text' onChange={this.handleChange} value={this.state.message} className="message_box" placeholder="enter message"/>
<button className="submit_message" onClick={this.handleSubmit}>Submit</button>
</div>
</div>
</div>
)
}
the problem i faced is the chat messages box starts at the topmost position of the container (scroll position starts at the top). I wanted the scroll position to be at the bottom like a normal chat room.
so i tried doing this:
componentDidMount(){
this.refs.messages.scrollTop = this.refs.messages.scrollHeight
}
this triggers AFTER the component gets mounted i.e - the message box scroll position initially starts at the top and forces its way to the bottom on render.
this is normally fine but i'm using a library called react-waypoint which would help me paginate chat messages. this gets triggered every time i'm at the top of the container.
the unhappy consequence is that because the message box starts at the top initially on mount, the waypoint always gets triggered on mount as well.
my question is whether i can force the message component to start at the bottom position as opposed to starting the top and going to the bottom at the beginning
I tried doing this
componentWillMount(){
this.refs.messages.scrollTop = this.refs.messages.scrollHeight
}
the problem is i dont have access to refs before the component mounts. is there any other way?
What you want is to avoid firing this.activateWayPoint before you've set scrollTop.
You can do this by setting a state variable waypointReady to false initially. Set it to true in componentDidMount.
Then, you can modify this.activateWayPoint to check this.state.waypointReady, and return immediately if it is false.
// inside component
getInitialState() {
return { waypointReady : false }
}
componentDidMount() {
this.refs.messages.scrollTop = this.refs.messages.scrollHeight;
this.setState({ waypointReady : true});
}
activateWayPoint() {
if (! this.state.waypointReady) return;
// Your code here!
// ...
}
You will probably have to bind this inside your render function:
// ...
<Waypoint onEnter={this.activateWayPoint.bind(this)}/>
// ...
Alternately, instead of performing the check inside this.activateWayPoint, you might perform the check inside render:
// ...
<Waypoint onEnter={
this.state.waypointReady ?
this.activateWayPoint :
null
}/>
// ...
This assumes that your component re-renders every time you setState.