React Redux Confirming Navigation - javascript

I'm trying to achieve a product page, which gives the Administrator an ability to modify the product details by clicking an edit button, but if the Admin tries to leave the page with changes that they have not yet saved, it would confirm that the user wants to leave the page without saving.
Here is what I currently have in my ProductForm.js, which is used by Product.js when Admin clicks edit.
import { browserHistory } from 'react-router';
componentWillReceiveProps() {
browserHistory.listenBefore(location => {
console.log(location);
return 'Are you sure you want to leave the page without saving?';
});
}
The issue with the following code is that when the user opens the edit form, this confirmation message shows on every page transition, even if you're not on the product page.
I am using the following skeleton. https://github.com/erikras/react-redux-universal-hot-example

You can cancel listener like this:
import { browserHistory } from 'react-router';
componentWillReceiveProps() {
const cancelListner = browserHistory.listenBefore(location => {
console.log(location);
cancelListner();
return 'Are you sure you want to leave the page without saving?';
});
}

Related

how to run firebase update once?

I have a button and when we press it, Firebase updates some value in Firebase. How can I control users? When we press it, Firebase updates some value in Firebase. How can I control users' presses? And allow the user to press this button only once?
My idea is that when opening some page in useEffect, I check if this user pressed a button earlier (I store all users' IDs to check if a user pressed a button) and if there is no user ID, then I allow the user to press the button, but if there is a user ID, then I disable the button and the user can't press it again.
But here is some problems. When user open page while firebase checks if there is user button is available for pressing. This is problem and I dont' want to allow do that.
And also if previosly user didn't press the button and now wants to do that then I need to imidiatelly disable it to prevent pressing it more than once.
How To disable button while data is fetched from firebase (on page loading)
How To disable button after 'click'
Here's a test component which accomplishes what you are asking:
import React, {useEffect, useState} from 'react';
import { Button } from 'react-native-paper';
const Test = props => {
const [isButtonDisabled, setIsButtonDisabled] = useState(false);
useEffect(() => {
const fetchMyAPI = async () => {
setIsButtonDisabled(true) // Disable button
let response = await fetch('api/data')
response = await response.json()
// Do whatever you want with response
setIsButtonDisabled(false) // Enable button after fetching
}
fetchMyAPI()
}, [])
const onPressHandler = () => {
setIsButtonDisabled(true)
// Button functionality can go here
}
return (
<Button onPress={onPressHandler} disabled={isButtonDisabled}></Button>
);
};
export default Test;
This is for react native so just replace the react native Button with whatever button you want to use.
Edit:
If you are having a problem with the button disabled state when reloading this component it is likely due to the component re-rendering. You will have to lift the state up to the parent and pass the state back down to the children. This will avoid the state being reset when the button gets re-rendered.
See the react docs https://reactjs.org/docs/lifting-state-up.html

React-router Prompt: How do I actually override the cancel behavior of the browser confirmation dialog?

Currently, I want to show a message to the user before the user navigates away from the page with unsaved changes. I looked into using react-router Prompt component and I have it setup like this:
import { Prompt } from 'react-router-dom';
function MyForm() {
const [isFormIncomplete, setIsFormIncomplete] = useState(true);
return (
<div>
<form>{/*form code*/}</form>
<Prompt
when={isFormIncomplete}
message="Are you sure you want to leave?" />
</div>
)
}
Currently, it showing the confirmation dialog just fine but I'm confused on how to override the cancel button. Right now, on cancel, it still navigates away from the page (same with ok) but on cancel, I just want to dismiss the browser confirmation dialog and not navigate away from the page. How do I do that? I don't see anything in the docs for overriding cancel behavior of the browser dialog?

How to redirect to the pages on back button click of different components in angular2?

I have 3 pages to implement this scenario.
Currently,
If I go to the first page and, click to navigate to the 2nd page. And then, on the 2nd page, I click the back button. It works fine (i.e, Navigates to 1st page).
Now, from 1st page, I go to the second page and, click to navigate to the 3rd page. And then, in the 3rd page, I click on back button, it redirects to the 2nd page as expected.
Now if I click on the back button on the second page, it goes to the 3rd page again. Where I want that to be redirected to the 1st page.
Here, actually according to code, it is working fine but my requirement is that
i have 2 pages company and companyApp where both pages have same guide and pin pages.. So, i want the guide page to redirect to company page, if i had been to guide page from company page even though guide page has been and come from images page.
If i had been to guide page from compnay app page then it must redirect to company app page even though it is again directed to images page and all.
So, can anyone help me to solve this:
TS:
// 1st Page:
goToGuide1(company){
this.router.navigate(['/guide',company.user._id]);
}
// 2nd page:
import {Location} from '#angular/common';
constructor(private _location: Location) {}
goToCompany1() {
this._location.back();
}
goImg(guide) {
this.router.navigate(['/guideimg', guide._id]);
}
// 3rd page
goToGuide1() {
this.router.navigate(['/guide',this.user_id])
}
Here on the 2nd page:
If I go to the Image page and click on back button, it comes to the guide page but doesn't go to the 1st page.
We use the benifits of localStorage and store the current Component and redirect accordingly,
Since you have,
{ path: 'company', component: CompanyComponent, canActivate:[AuthGuard] },
{ path: 'companyapp', component: CompanyAppComponent, canActivate:[AuthGuard] }
In Company Component:
goToGuide(company){
this.localStorage.store('oldroute', 'company')
this.router.navigate(['/guide',company.user._id]);
}
in companyApp Component:
goToGuide(company){
this.localStorage.store('oldroute', 'companyapp')
this.router.navigate(['/guide',company.user._id]);
}
In Guide Component,
goToCompany() {
if(this.localStorage.retrieve('oldroute') && (this.localStorage.retrieve('oldroute') == 'companyApp'))
{
this.router.navigate(['/companyApp']);
}else{
this.router.navigate(['/company']);
}
}
Reason for the behavior: It is happening because of the 3rd page is stored in the location attribute.
Angular API documentation states that,
"Note: it's better to use Router service to trigger route changes. Use Location only if you need to interact with or create normalized URLs outside of routing."
The possible solution for your issues are,
Write a service which saves the whole user navigation history into a data structure and also to retrieve it when we need it.
Append the redirecting state through query parameters so that, using a conditional you can check that on the current page.
I'd possibly go with the option 1 if I have the same behavior several times in my entire application. but here the 2nd option would do.
While redirecting from any of the pages add the page detail into the queryParams and redirect.
Ex - If that's from the company page,
[routerLink]="['/guide', <anyId>]" [queryParams]="{from: 'company'}"
or
goToGuide1(company){
this.router.navigate(['/guide',company.user._id], { queryParams: { 'from': 'company' } });
}
So when you redirect to back you can check with a conditional and redirect back.
// Import
import { ActivatedRoute } from '#angular/router';
// Inject
constructor(
private route: ActivatedRoute
) {
// store the previous state
this.route.queryParams.subscribe(params => {
this.redirectedFrom = params['from'];
}
}
// check the condition while redirect
goToBackState() { // can go as goToCompany
if (this.redirectedFrom === company) {
// redirect to company
} else {
// otherwise redirect to companyApp
// Please note that you can check for the companyApp as well.
}
}
It is all about how you handle the conditional logic and overall logic as well. If you identify those and do it right,
Then it should work as it is expected.

Custom Modal Dialog Box in Browser back in Angular 4+

Suppose my current route is /transact/orders and is in Order summary view, What I want to do is to open a custom dialog which gives the option to add to cart or cancel button when he/she presses browser back button of the browser.If user press add to cart button it goes to the cart or else the browser back button functionality will happen. Currently, I am using Angular 5.2.I would like to know if it is possible with LocationStrategy.I searched but could not get a proper example of it.Can anybody explain with proper example?
You can subscribe to Location events anywhere you want to do actions on back button pressed:
import { Subscription } from 'rxjs/Subscription';
ngOnInit() {
this.subscription = <Subscription> this.location.subscribe( () => {
// your code here
} );
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
Don't forget to unsubscribe in OnDestroy.
EDIT: location should be type Location, not LocationStrategy

Prevent component from unmounting - showing notification to users before opening other component

In my web app there is a form where users put in data. If they want to navigate to other component or back, I want to notify them that changes were made to form and show them confirmation dialog.
I know how to implement this if users click on back button on top of the form, but don't have any idea how to handle it when users click on sidebar menu options. (there is a sidebar with multiple links to other components - using react-router).
I have tried something using componentWillunmount() but no luck since component gets unmounted in any case.
If anyone has experience in this I would really need some help.
Try the routerWillLeave hook, here is a example from react-router's documentation:
const Home = withRouter(
React.createClass({
componentDidMount() {
this.props.router.setRouteLeaveHook(this.props.route, this.routerWillLeave)
},
routerWillLeave(nextLocation) {
// return false to prevent a transition w/o prompting the user,
// or return a string to allow the user to decide:
if (!this.state.isSaved)
return 'Your work is not saved! Are you sure you want to leave?'
},
// ...
})
)
https://github.com/ReactTraining/react-router/blob/master/docs/guides/ConfirmingNavigation.md

Categories

Resources