Reputation: 12855
I am using angular 2 with hashlocation
strategy.
The component is loaded with that route:
"departments/:id/employees"
So far fine.
After I do a successful batch save of multiple edited table rows I want to reload the current route URL via:
this.router.navigate([`departments/${this.id}/employees`]);
But nothing happens, why?
Upvotes: 280
Views: 609524
Reputation: 2250
Suppose that the component's route you want to refresh is view
, then use this:
this.router.routeReuseStrategy.shouldReuseRoute = function (future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot) {
if (future.url.toString() === 'view' && curr.url.toString() === future.url.toString()) {
return false;
}
return (future.routeConfig === curr.routeConfig);
};
you can add a debugger
inside the method to know what is the exact route will come after navigate to "departments/:id/employees"
.
refer to this answer for more detailed solution.
Upvotes: 1
Reputation: 3115
Create a function in the controller that redirects to the expected route like this:
redirectTo(uri: string) {
this.router.navigateByUrl('/', { skipLocationChange: true }).then(() => {
this.router.navigate([uri])});
}
Then you use it like this
this.redirectTo('//place your uri here');
This function will redirect to a dummy route and quickly return to the destination route without the user realizing it.
Upvotes: 309
Reputation: 4193
I am using this one for Angular 11 project:
reloadCurrentRoute() {
const currentUrl = this.router.url;
this.router.navigateByUrl('/', { skipLocationChange: true }).then(() => {
this.router.navigate([currentUrl]);
});
}
PS: Tested and works on all versions above 7.
Upvotes: 115
Reputation: 1
In file html:
<a class="clicable" (click)="menu('/proyects')">Proyects</a>
in file ts:
menu(uri:string){
if(this.router.url == uri){
window.location.reload();
}else{
this.router.navigate([uri])
}
}
Upvotes: 0
Reputation: 1102
This is what I did with Angular 12. I'm not sure does this works in versions below 9.
You will need to call this when you need to reload.
this.router.navigate([], {
skipLocationChange: true,
queryParamsHandling: 'merge' //== if you need to keep queryParams
})
Router forRoot needs to have SameUrlNavigation set to 'reload'
RouterModule.forRoot(appRoutes, {
// ..
onSameUrlNavigation: 'reload',
// ..
})
And your every route needs to have runGuardsAndResolvers set to 'always'
{
path: '',
data: {},
runGuardsAndResolvers: 'always'
},
Upvotes: 60
Reputation: 711
Write a function—e.g., reloadCurrentPage
. As window
is a global object which can be reused directly in Angular components, window.location.reload()
reloads the currently active page.
function reloadCurrentPage() {
window.location.reload();
}
Upvotes: 3
Reputation: 56
using 'timestamp' is a cheap and amazing way.
this.router.navigate([], {
relativeTo: this.route,
queryParams: {
...this.route.snapshot.queryParams,
// replace 't' with any others not to conflict with exsiting
// '2^11' prevents reloading in about 2 seconds
t: Date.now() >> 11,
skipLocationChange: true,
},
});
Upvotes: 1
Reputation: 1069
Another option is to use plain js but the page will actually refresh.
window.location.reload(true)
Upvotes: -4
Reputation: 1566
Subscribe to URL params and initialize component there. No tricks, just "new URL --> new data", including first time loading.
For URL params (like /persons/:id
):
constructor(protected activeRoute: ActivatedRoute, ...) {
this.activeRoute.paramMap.subscribe(paramMap => {
const id = paramMap.get('id'); // get param from dictonary
this.load(id); // load your data
});
}
For URL query params (like ?q=...&returnUrl=...
) (usually not required):
this.activeRoute.queryParamMap.subscribe(queryParamMap => {
const returnUrl = queryParamMap.get('returnUrl');
...
});
When URL changes, Angular will reuse old component if possible to save computer's resources. Loading of data is your custom code, so that Angular can't do it for you.
Upvotes: 6
Reputation: 4649
I have tried a few fixes and none of them works. My version is simple: add a new unused parameter into query parameters
if (force) {
let key = 'time';
while (key in filter) {
key = '_' + key;
}
filter[key] = Date.now();
}
this.router.navigate(['.', { filter: JSON.stringify(filter) }]);
Upvotes: 0
Reputation: 648
Decides when the route should be stored return false to
this.router.routeReuseStrategy.shouldReuseRoute = function () {
return false;
};
and set the navigated value of router to false, that show that this route never routed
this.mySubscription = this.router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
this.router.navigated = false;
}
});
Upvotes: 0
Reputation: 2947
Import Router
and ActivatedRoute
from @angular/router
import { ActivatedRoute, Router } from '@angular/router';
Inject Router
and ActivatedRoute
(in case you need anything from the URL)
constructor(
private router: Router,
private route: ActivatedRoute,
) {}
Get any parameter if needed from URL.
const appointmentId = this.route.snapshot.paramMap.get('appointmentIdentifier');
Using a trick by navigating to a dummy or main url then to the actual url will refresh the component.
this.router.navigateByUrl('/appointments', { skipLocationChange: true }).then(() => {
this.router.navigate([`appointment/${appointmentId}`])
});
const id= this.route.snapshot.paramMap.get('id');
this.router.navigateByUrl('/departments', { skipLocationChange: true }).then(() => {
this.router.navigate([`departments/${id}/employees`]);
});
If you use a dummy route then you will see a title blink 'Not Found' if you have implemented a not found url in case does not match any url.
Upvotes: 4
Reputation: 8423
EDIT
For newer versions of Angular (5.1+) use answer suggested by @Simon McClive
Old answer
I found this workaround on a GitHub feature request for Angular:
this._router.routeReuseStrategy.shouldReuseRoute = function(){
return false;
};
this._router.events.subscribe((evt) => {
if (evt instanceof NavigationEnd) {
this._router.navigated = false;
window.scrollTo(0, 0);
}
});
I tried adding this to my app.component.ts ngOnInit
function, and it sure worked. All further clicks on the same link now reloads the component
and data.
Link to original GitHub feature request
Credit goes to mihaicux2 on GitHub.
I tested this on version 4.0.0-rc.3
with import { Router, NavigationEnd } from '@angular/router';
Upvotes: 82
Reputation: 3580
Very frustrating that Angular still doesn't seem to include a good solution for this. I have raised a github issue here: https://github.com/angular/angular/issues/31843
In the meantime, this is my workaround. It builds on some of the other solutions suggested above, but I think it's a little more robust. It involves wrapping the Router service in a "ReloadRouter
", which takes care of the reload functionality and also adds a RELOAD_PLACEHOLDER
to the core router configuration. This is used for the interim navigation and avoids triggering any other routes (or guards).
Note: Only use the ReloadRouter
in those cases when you want the reload functionality. Use the normal Router
otherwise.
import { Injectable } from '@angular/core';
import { NavigationExtras, Router } from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class ReloadRouter {
constructor(public readonly router: Router) {
router.config.unshift({ path: 'RELOAD_PLACEHOLDER' });
}
public navigate(commands: any[], extras?: NavigationExtras): Promise<boolean> {
return this.router
.navigateByUrl('/RELOAD_PLACEHOLDER', {skipLocationChange: true})
.then(() => this.router.navigate(commands, extras));
}
}
Upvotes: 2
Reputation: 191
I believe this has been solved (natively) in Angular 6+; check
But this works for an entire route (includes all children routes as well)
If you want to target a single component, here's how: Use a query param that changes, so you can navigate as many times as you want.
At the point of navigation (class)
this.router.navigate(['/route'], {
queryParams: { 'refresh': Date.now() }
});
In Component that you want to "refresh/reload"
// . . . Component Class Body
$_route$: Subscription;
constructor (private _route: ActivatedRoute) {}
ngOnInit() {
this.$_route$ = this._route.queryParams.subscribe(params => {
if (params['refresh']) {
// Do Something
// Could be calling this.ngOnInit() PS: I Strongly advise against this
}
});
}
ngOnDestroy() {
// Always unsubscribe to prevent memory leak and unexpected behavior
this.$_route$.unsubscribe();
}
// . . . End of Component Class Body
Upvotes: 0
Reputation: 31
This below code will work:
logoFn(url: any) {
this.router.routeReuseStrategy.shouldReuseRoute = function () {
return false;
};
this.router.navigate(['']); or
this.router.navigate([url]);
}
Upvotes: 0
Reputation: 131
If you are changing route via Router Link Follow this:
constructor(public routerNavigate: Router){
this.router.routeReuseStrategy.shouldReuseRoute = function () {
return false;
};
this.router.events.subscribe((evt) => {
if (evt instanceof NavigationEnd) {
this.router.navigated = false;
}
})
}
Upvotes: 0
Reputation: 251
I am using setTimeout
and navigationByUrl
to solve this issue... And it is working fine for me.
It is redirected to other URL and instead comes again in the current URL...
setTimeout(() => {
this.router.navigateByUrl('/dashboard', {skipLocationChange: false}).then(() =>
this.router.navigate([route]));
}, 500)
Upvotes: 2
Reputation: 401
There are different approaches to refresh the current route
Change router behaviour (Since Angular 5.1) Set the routers onSameUrlNavigation to 'reload'. This will emit the router events on same URL Navigation.
Leave the router untouched
I have written a more detailed explanation under https://medium.com/@kevinkreuzer/refresh-current-route-in-angular-512a19d58f6e
Hope this helps.
Upvotes: 2
Reputation: 1491
A little bit hardcore but
this.router.onSameUrlNavigation = 'reload';
this.router.navigateByUrl(this.router.url).then(() => {
this.router.onSameUrlNavigation = 'ignore';
});
Upvotes: 3
Reputation: 63
A solution is to pass a dummy parameter (i.e. the time in seconds), in this way the link is always reloaded:
this.router.navigate(["/url", {myRealData: RealData, dummyData: (new Date).getTime()}])
Upvotes: 3
Reputation: 2733
This works for me like a charm
this.router.navigateByUrl('/', {skipLocationChange: true}).then(()=>
this.router.navigate([<route>]));
Upvotes: 40
Reputation: 810
Found a quick and straight-forward solution that doesn't require to tinker with the inner workings of angular:
Basically: Just create an alternate route with the same destination module and just toggle between them:
const routes: Routes = [
{
path: 'gesuch',
loadChildren: './sections/gesuch/gesuch.module#GesuchModule'
},
{
path: 'gesuch-neu',
loadChildren: './sections/gesuch/gesuch.module#GesuchModule'
}
];
And here the toggeling menu:
<ul class="navigation">
<li routerLink="/gesuch-neu" *ngIf="'gesuch' === getSection()">Gesuch</li>
<li routerLink="/gesuch" *ngIf="'gesuch' !== getSection()">Gesuch</li>
</ul>
Hope it helps :)
Upvotes: 6
Reputation: 167
On param change reload page won't happen. This is really good feature. There is no need to reload the page but we should change the value of the component. paramChange method will call on url change. So we can update the component data
/product/: id / details
import { ActivatedRoute, Params, Router } from ‘@angular/router’;
export class ProductDetailsComponent implements OnInit {
constructor(private route: ActivatedRoute, private router: Router) {
this.route.params.subscribe(params => {
this.paramsChange(params.id);
});
}
// Call this method on page change
ngOnInit() {
}
// Call this method on change of the param
paramsChange(id) {
}
Upvotes: 12
Reputation: 15558
Solved a similar scenario by using a dummy component and route for reload
, which actually does a redirect
. This definitely doesn't cover all user scenarios but just worked for my scenario.
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Http } from '@angular/http';
@Component({
selector: 'reload',
template: `
<h1>Reloading...</h1>
`,
})
export class ReloadComponent implements OnInit{
constructor(private router: Router, private route: ActivatedRoute) {
}
ngOnInit() {
const url = this.route.snapshot.pathFromRoot.pop().url.map(u => u.path).join('/');
this.router.navigateByUrl(url);
}
}
The routing is wired to catch all urls using a wildcard:
import { RouterModule } from '@angular/router';
import { NgModule } from '@angular/core';
import { LoginViewComponent } from './views/login/login.component';
import { HomeViewComponent } from './views/home/home.component';
import { ReloadComponent } from './views/reload/reload.component';
@NgModule({
declarations: [
LoginViewComponent, HomeViewComponent, ReloadComponent
],
imports: [
RouterModule.forRoot([
{ path: 'login', component: LoginViewComponent },
{ path: 'home', component: HomeViewComponent },
{
path: 'reload',
children: [{
path: '**',
component: ReloadComponent
}]
},
{ path: '**', redirectTo: 'login'}
])
],
exports: [
RouterModule,
],
providers: [],
})
export class AppRoutingModule {}
To use this, we just need to add reload to the url where we want to go:
this.router.navigateByUrl('reload/some/route/again/fresh', {skipLocationChange: true})
Upvotes: 2
Reputation: 3030
subscribe to route parameter changes
// parent param listener ie: "/:id"
this.route.params.subscribe(params => {
// do something on parent param change
let parent_id = params['id']; // set slug
});
// child param listener ie: "/:id/:id"
this.route.firstChild.params.subscribe(params => {
// do something on child param change
let child_id = params['id'];
});
Upvotes: 0
Reputation: 2616
This can now be done in Angular 5.1 using the onSameUrlNavigation
property of the Router config.
I have added a blog explaining how here but the gist of it is as follows
In your router config enable onSameUrlNavigation
option, setting it to 'reload'
. This causes the Router to fire an events cycle when you try to navigate to a route that is active already.
@ngModule({
imports: [RouterModule.forRoot(routes, {onSameUrlNavigation: 'reload'})],
exports: [RouterModule],
})
In your route definitions, set runGuardsAndResolvers
to always
. This will tell the router to always kick off the guards and resolvers cycles, firing associated events.
export const routes: Routes = [
{
path: 'invites',
component: InviteComponent,
children: [
{
path: '',
loadChildren: './pages/invites/invites.module#InvitesModule',
},
],
canActivate: [AuthenticationGuard],
runGuardsAndResolvers: 'always',
}
]
Finally, in each component that you would like to enable reloading, you need to handle the events. This can be done by importing the router, binding onto the events and invoking an initialisation method that resets the state of your component and re-fetches data if required.
export class InviteComponent implements OnInit, OnDestroy {
navigationSubscription;
constructor(
// … your declarations here
private router: Router,
) {
// subscribe to the router events. Store the subscription so we can
// unsubscribe later.
this.navigationSubscription = this.router.events.subscribe((e: any) => {
// If it is a NavigationEnd event re-initalise the component
if (e instanceof NavigationEnd) {
this.initialiseInvites();
}
});
}
initialiseInvites() {
// Set default values and re-fetch any data you need.
}
ngOnDestroy() {
if (this.navigationSubscription) {
this.navigationSubscription.unsubscribe();
}
}
}
With all of these steps in place, you should have route reloading enabled.
Upvotes: 206
Reputation: 126
implement OnInit and call ngOnInit() in method for route.navigate()
See an example :
export class Component implements OnInit {
constructor() { }
refresh() {
this.router.navigate(['same-route-here']);
this.ngOnInit(); }
ngOnInit () {
}
Upvotes: 3
Reputation: 193
Try this
window.open('dashboard', '_self');
its old method but works on all angular version, where it redirect on route and refresh the page.
Upvotes: -3
Reputation: 10378
reload current route in angular 2 very helpful link to reload current route in angualr 2 or 4
in this define two technique to do this
for more see above link
Upvotes: -2