Reloading current route in Angular 5 / Angular 6 / Angular 7
问题: angular 从子状态回到当前的父级状态的时候,父级状态不会重新初始化。
https://github.com/angular-ui/ui-router/issues/2992

------------------------------------------------
Back in the days of AngularJS you were able to reload a route even if you were already viewing it. For example, clicking on the home option of a menu when you are already viewing the homepage would refresh the homepage. This was useful for a number of reasons, but most importantly for UX. Users expect to be able to click on a page menu item and have the page re-initialise. Setting up this type of reloading in AngularJS was straightforward. You could invoke reload() in your router and away you went.
When Angular 2 was released this feature was not present in the router and there was no easy way to reload the active route. Many people developed “hacky” techniques such as bouncing through a second route in the A -> B -> A sequence, effectively sending you off to a page and back again to trigger the reload. That had the desired effect but was rather inefficient. Another technique that was often suggested was outright reloading the page, which for a single page application is a bad idea.
As of Angular 5.1 there is a supported technique for route reloading. This can now be done using the onSameUrlNavigation
configuration option as part of the built-in Angular router. Unfortunately, the documentation does not make it very clear on how to implement it, so I have documented my approach below.
The first thing you will need to do is set the option within your app.routing.tsif you have one, or the file where your app routing is configured in your particular project.
There are two possible values for onSameUrlNavigation ’reload’ or false. The default value is false, causing 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 how those events are actually fired, you need to specify the runGuardsAndResolvers configuration option on your route. This can take one of 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 definition is shown below.
export const routes: Routes = [
{
path: ‘invites’,
component: InviteComponent,
children: [
{
path: ‘’,
loadChildren: ‘./pages/invites/invites.module#InvitesModule’,
},
],
canActivate: [AuthenticationGuard],
runGuardsAndResolvers: ‘always’,
}
]
With these two changes your router is configured. The next step is to handle the events that your router will produce within one of your components. To do this you will need to import the Router into your component and then hook into the events of interest. In this example, I have hooked into the NavigationEnd event which is fired once the router has completed its navigation from one route to another. 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, OnDestroy{
// ... your class variables here
navigationSubscription;
constructor(
// … your declarations here
private router: Router,
) {
// subscribe to the router events - storing 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() {
// avoid memory leaks here by cleaning up after ourselves. If we
// don't then we will continue to run our initialiseInvites()
// method on every navigationEnd event.
if (this.navigationSubscription) {
this.navigationSubscription.unsubscribe();
}
}
}
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 would like to to reload, being sure to add the runGuardsAndResolvers option to each route in the routing file.
** Updated 05/03/2018 **
Thanks to Changyu Geng and Dennis de Laat for pointing this out in the comments.
I have added an unsubscribe handler in the ngOnDestroy hook in the above example.
As router.events is global, if we do not unsubscribe our event handler on component destruction then it will continue to fire for every NavigationEndevent across our application even when we are not on the invites screen. This is less than ideal because
a) We will be running our event handler for invites even if we are on another screen.
b) Every time we navigate back to invites we will resubscribe to the event. This would cause our initialise function to run n times, where n is the number of times we have landed on the invites page.
If you’ve enjoyed this blog, please take a couple of minutes to check out Gurn and see how it can make you a more productive developer.
---------------------------------------------------------------------------
2I want to extract only the last event entry of type NavigationEnd from router.events. But somehow I can't find a proper way to do this. Whatever I try the following code snipped is the only way to get access to these objects of interest.
let ne: any; router.events.filter(e => e instanceof NavigationEnd)
.forEach(e => {
ne = e as NavigationEnd;
}); console.log('target page: ', ne.urlAfterRedirects);But do I really have to use .forEach() letting it run though all entries and using then the last entry? Isn't there a better way to handle the events as a kind of array and then say
ne = arrayOfEvents[arrayOfEvents.length-1]?
I'm getting crazy about it but it seems that I can't see the wood for the trees...
1Have you looked at using thelastoperator on observables? reactivex.io/documentation/operators/last.html – Daniel W Strimpel Apr 8 '18 at 20:29 Yes, I tried it. But it unfortunately doesn't work in my case as there is no processable return value. – Lynx 242Apr 8 '18 at 20:45 2Did you see this article? toddmotto.com/dynamic-page-titles-angular-2-router-events – Vega Apr 8 '18 at 20:49 1That's it! This helps a lot. Thank you. – Lynx 242 Apr 8 '18 at 21:00 If the events observable never completes thenlastnever does anything. What do you mean by last? YOUmean the last in the group. But the computer can wait 100 years for the stream to close, and that's whatlast()means to RxJS! So I think actuallylast()will NEVER return (it possibly might as the page is being unloaded but that's no use). – Simon_Weaver Jan 23 at 22:104Okay, after reading through the posted articles above and rethinking what I really want to achieve I found out that my approach was definitely too complicated. Because actually I only need access to the currently called route. And so I started from scratch and came across this small but very effective solution:
this.router.events.subscribe(value => {
console.log('current route: ', router.url.toString());
});Thanks to all who shared a comment in oder to support me! It helped al lot as I was able to tie up loose ends.
4PS. There's a better way to filter using a 'typeguard', you then get the proper type without having to assert it again:
firstChildData$ = this.router.events.pipe( filter((e): e is NavigationEnd => e instanceof NavigationEnd), map(e => { // e is now NavigationEnd }
This is actually necessary in strict mode.
Reloading current route in Angular 5 / Angular 6 / Angular 7的更多相关文章
- Angular学习笔记:Angular CLI
定义 Angular CLI:The Angular CLI is a command line interface tool that can create a project, add files ...
- angular enter事件,angular回车事件
angular回车键搜索,angular enter搜索 对于搜索框,用户在输入内容后的搜索习惯不是鼠标点击搜索按钮,而是直接按enter键,那我们怎么给enter键绑定事件呢,其实很简单,代码如下: ...
- Angular 2 升级到 Angular 5
Angular 2 升级到 Angular 5 ts文件最上面的import语句里不要添加 .ts 后缀 , 不然 npm start 编译会失败 . 虽然浏览器能打开项目的URL , 但是内容会丢失 ...
- Angular系列一:Angular程序架构
Angular程序架构 Angular程序架构 组件:一段带有业务逻辑和数据的Html服务:用来封装可重用的业务逻辑指令:允许你向Html元素添加自定义行为模块: 环境搭建 安装nodeJs安装好no ...
- Angular系列文章之angular路由
路由(route),几乎所有的MVC(VM)框架都应该具有的特性,因为它是前端构建单页面应用(SPA)必不可少的组成部分. 那么,对于angular而言,它自然也有内置的路由模块:叫做ngRoute. ...
- [Angular 2] ROUTING IN ANGULAR 2 REVISITED
Let's say we have a list of contacts, click each contact, we can render a new route to get the detai ...
- Angular - 预加载 Angular 模块
Angular - 预加载延迟模块 在使用路由延迟加载中,我们介绍了如何使用模块来拆分应用,在访问到这个模块的时候, Angular 加载这个模块.但这需要一点时间.在用户第一次点击的时候,会有一点延 ...
- Angular企业级开发(3)-Angular MVC实现
1.MVC介绍 Model-View-Controller 在20世纪80年代为程序语言Smalltalk发明的一种软件架构.MVC模式的目的是实现一种动态的程序设计,使后续对程序的修改和扩展简化,并 ...
- 30行代码让你理解angular依赖注入:angular 依赖注入原理
依赖注入(Dependency Injection,简称DI)是像C#,java等典型的面向对象语言框架设计原则控制反转的一种典型的一种实现方式,angular把它引入到js中,介绍angular依赖 ...
随机推荐
- Tengine编译安装+lua+sticky模块
一.两个依赖包 有yum的直接 yum yum –y install openssl openssl-devel prce prce-devel zlib zlib-devel 没有yum环境的, ...
- python线程信号量semaphore(33)
通过前面对 线程互斥锁lock / 线程事件event / 线程条件变量condition / 线程定时器timer 的讲解,相信你对线程threading模块已经有了一定的了解,同时执行多个线程的 ...
- RAID(独立磁盘冗余阵列)
Raid RAID 独立磁盘冗余阵列,在本科学习时候学习过,记不清是组成原理还是操作系统,当时理解的不太清楚,现在研究生期间做存储相关项目,涉及到了Raid,于是查各种博客,为了以后便于后期查阅, ...
- 自定义模块,time,datetime以及random
自定义模块,time,datetime以及random 1.自定义模块 自定义一个模块 import #导入 (拿工具箱) 模块分类 1.内置模块(标准库) --python解释器自带的.py文件(模 ...
- docker 实践一:简介和安装
docker 的简介 docker 绝对是这几年来的重量级开源软件,它是使用 Go 实现的开源容器项目,分属于虚拟化技术. docker 和 虚拟机 docker 作为一种轻量级的虚拟化方式,在运行应 ...
- 剑指offer(3)——二维数组中的查找
题目: 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 思路: 首先选取数组中右上 ...
- linux中部署jenkins(war包)及jenkins忘记登录账号密码
未登录状态 登录状态 一:部署jenkins(war包) 1.直接下载war包jenkins.war,下载地址https://jenkins.io/download 2.将下载的war包放到服务器上t ...
- Linux 截取日志命令
1.截取时间段 截取 2019-06-25 10:10 到 2019-06-25 10:20 之间的日志记录,apollo-service.log 为你要截取的文件名称, new2.log 截取之后保 ...
- C# wsdl.exe 生成类文件
wsdl.exe D:\XXX\demand\demand.\wsdl\XXX.wsdl /\wsdl\class 在 vs tools:Developer Command Prompt For VS ...
- 【Transact-SQL】找出不包含字母、不包含汉字的数据
原文:[Transact-SQL]找出不包含字母.不包含汉字的数据 测试的同事,让我帮忙写个sql语句,找出表中xx列不包含汉字的行. 下面的代码就能实现. IF EXISTS(SELECT * FR ...
angular
