I have recently updated to the new RC3 and Router3alpha and it seems some things have changed.
I noticed that a click on the link of an active route does no longer result in the component to be reloaded. How do I achieve this behaviour with the new router3?
My link looks like
<a [routerLink]="['/link1']">Link1</a>
And to test I simply used a random number in ngOnInit:
export class LinkoneComponent implements OnInit
{
public foo: number;
constructor() {}
ngOnInit()
{
this.foo = Math.floor(Math.random() * 100) + 1;
}
}
It works just fine when switiching between routes, but a click on the currently active route does not result in a reload of the component.
This is currently not supported. If only parameter values change but the route stays the same the component is not re-created.
See also https://github.com/angular/angular/issues/9811
You can subscribe to params to get notified when the params change to re-initialize the component instance.
See also https://stackoverflow.com/a/38560010/217408
Angular 2-4 current route reload hack
For me, using this method works:
onRefresh() {
this.router.routeReuseStrategy.shouldReuseRoute = function(){return false;};
let currentUrl = this.router.url + '?';
this.router.navigateByUrl(currentUrl)
.then(() => {
this.router.navigated = false;
this.router.navigate([this.router.url]);
});
}
You can attach this method to a click event on the current component to reload it.
As of Angular 5.1 this can now be done by using the onSameUrlNavigation
configuration option as part of the built-in Angular router. It's fairly straightforward to set-up and get going although not obvious from the documentation.
The first thing you will need to do is set the option within your app.routing.ts
if you have one or the file where your app routing is configured.
There are two possible values for onSameUrlNavigation 'reload'
or false
. The default value is false
which causes nothing to happen when the router is asked to navigate to the active route. We want to set this value to reload
. It is worth noting reload
does not actually do the work of reloading the route, it only re-triggers events on the router that we then need to hook into.
@NgModule({
imports: [RouterModule.forRoot(routes, {onSameUrlNavigation: 'reload'})],
exports: [RouterModule],
})
To determine when those events are actually fired, you need to specify the runGuardsAndResolvers
configuration option on your route. This can take three values...
paramsChange
- only fire when route params have changed e.g. where the id in /user/:id
changes
paramsOrQueryParamsChange
- fire when a route param changes or a query param changes. e.g. the id
or the limit
property change in /user/:id/invites?limit=10
always
- Always fire when the route is navigated
We want to specify always in this case. An example route is shown below.
export const routes: Routes = [
{
path: 'invites',
component: InviteComponent,
children: [
{
path: '',
loadChildren: './pages/invites/invites.module#InvitesModule',
},
],
canActivate: [AuthenticationGuard],
runGuardsAndResolvers: 'always',
}
]
That is your router configured. The next step is to actually handle the events within one of your components. You will need to import the Router into your component and then hook into the events. In this example, I have hooked into the NavigationEnd
event which is fired once the router has completed its navigation from one route to the next. Due to the way we have configured the app, this will now fire even if you try to navigate to the current route.
export class InviteComponent implements OnInit {
constructor(
// ... your declarations here
private router: Router,
) {
// subscribe to the router events
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.
}
}
The heavy lifting goes into the initialiseInvites()
method, this is where you reset properties to their default values and fetch data from services to get the component back to its initial state.
You need to repeat this pattern across each component that you want to be able to reload when clicked or refresh through some form of refresh button, being sure to add the runGuardsAndResolvers
option to each route in the routing file.
this worked for me, taken from this:
redirectTo(uri) {
this.router.navigateByUrl('/', {skipLocationChange: true}).then(() =>
this.router.navigate([uri]));
}
now you can use like: this.redirectTo(this.router.url)
;
For Angular 2 rc7 - router 3.0
Change base url in index.html to <script>document.write('<base href="/" />');</script>
This is the best hack that I've been able to come up to get around this annoying problem:
var currentUrl = this.router.url;
var refreshUrl = currentUrl.indexOf('someRoute') > -1 ? '/someOtherRoute' : '/someRoute';
this.router.navigateByUrl(refreshUrl).then(() => this.router.navigateByUrl(currentUrl));
This works, but it's still a hack and I hate that the Angular
team didn't provide a reload()
method
if (currentUrl.indexOf('/settings') > -1) {
this.router.navigateByUrl('/communication').then(() => this.router.navigateByUrl('/settings'));
} else {
this.router.navigate(['/settings']);
}
If you really need to trick the Router into reloading the component on each routerLink click, you can use the following code in your Component
constructor(private router: Router){
// override the route reuse strategy
this.router.routeReuseStrategy.shouldReuseRoute = function(){
return false;
}
this.router.events.subscribe((evt) => {
if (evt instanceof NavigationEnd) {
// trick the Router into believing it's last link wasn't previously loaded
this.router.navigated = false;
// if you need to scroll back to top, here is the right place
window.scrollTo(0, 0);
}
});
}
Hope this helps
In my modest opinion you could use the window.location.reload()
in typescript.
This way can be easy and secure because is a part of the browser functionalities.