typescript Angular 5 在路线更改之前添加事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/47986277/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular 5 add event before the route change
提问by Js Lim
I'm want to add a alert dialog before the user click on the <a href="...">
link.
我想在用户单击<a href="...">
链接之前添加一个警报对话框。
There are 2 types of <a>
link
有两种类型的<a>
链接
- Redirect within Angular scope
<a routerLink="/path/to/dest">
- Redirect outside of Angular app
<a href="http://www.somewhere.com" target="_blank">
- 在 Angular 范围内重定向
<a routerLink="/path/to/dest">
- 在 Angular 应用程序之外重定向
<a href="http://www.somewhere.com" target="_blank">
I want to able to show an alert box when user try to go outside of Angular scope
当用户尝试超出 Angular 范围时,我希望能够显示一个警告框
I want to apply to all <a>
click event (kind like pre-hook)
我想申请所有的<a>
点击事件(有点像 pre-hook)
Any way to achieve this?
有什么方法可以实现这一目标吗?
采纳答案by Js Lim
I achieve it by creating a component for <a>
, confirmation dialog component, and service for the dialog
我通过为<a>
、确认对话框组件和对话框创建服务来实现它
The confirm dialog
确认对话框
I'm using Angular Material
我正在使用角材料
import { Component, Inject, Output, EventEmitter } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
@Component({
selector: 'confirm-dialog',
templateUrl: './confirm-dialog.component.html',
})
export class ConfirmDialogComponent {
constructor(
public translate:TranslateService,
public dialogRef: MatDialogRef<ConfirmDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any
) {
}
onClick(result): void {
this.dialogRef.close(result);
}
}
the html file
html文件
<h1 mat-dialog-title>{{data.title}}</h1>
<div mat-dialog-content>
<h4 class="card-title">{{ data.message }}</h4>
</div>
<div mat-dialog-actions class="pull-right">
<a *ngIf="data.confirm_link" class="btn btn-primary" mat-button tabindex="-1" href="{{ data.confirm_link }}" target="_blank" (click)="onClick(true)">{{ data.confirm_button }}</a>
<button *ngIf="!data.confirm_link" class="btn btn-primary" mat-button tabindex="-1" (click)="onClick(true)"> {{ data.confirm_button }} </button>
<button class="btn btn-info" mat-button tabindex="-1" (click)="onClick(false)">Cancel</button>
</div>
The service
服务
Once the component is created, I want to make it easy to call from anywhere, so create a service for it
创建组件后,我希望可以轻松地从任何地方调用,因此为它创建一个服务
import { Injectable, OnDestroy} from "@angular/core";
import { Subject } from 'rxjs/Subject';
import { MatDialog } from '@angular/material';
import { ConfirmDialogComponent } from 'path/to/confirm-dialog/confirm-dialog.component';
import * as _ from 'lodash';
@Injectable()
export class ConfirmService implements OnDestroy{
private subject = new Subject<any>();
private message = 1;
info: any;
constructor(private dialog: MatDialog){
}
show(data: any){
let dialogRef = this.dialog.open(ConfirmDialogComponent, {
width: '500px',
data: data,
});
dialogRef.afterClosed().subscribe(result => {
this.subject.next(result);
});
return this.subject;
}
ngOnDestroy() {
}
}
The custom <a>
element
自定义<a>
元素
To make it easier to use in .htmlfile, I create a component for it
为了更容易在.html文件中使用,我为它创建了一个组件
import { Component, OnInit, Input } from '@angular/core';
import { ConfirmService } from 'path/to/service/confirm.service';
@Component({
selector: 'a-external',
templateUrl: './a-external.component.html',
})
export class AExternalComponent implements OnInit {
@Input('href') href: string;
@Input('class') classes: string;
@Input('content') content: string;
constructor(
private confirmService:ConfirmService,
) { }
ngOnInit() {
}
onAClick() {
var dialog = this.confirmService.show({
'title': 'Warning',
'message': 'This will open a new tab',
'confirm_button': 'open',
'confirm_link': this.href, // if pass in the uri, will open in new tab
});
var subscription = dialog.subscribe((result) => {
// if the result is true, means Confirm button is clicked
// if the result is false, means Cancel button is clicked
subscription.unsubscribe();
});
}
}
The confirm_link
is only applicable for open a new tab. Without the value, it will just trigger the dialog subscription result.
该confirm_link
只适用于打开一个新标签。如果没有该值,它只会触发对话框订阅结果。
And the html file is very simple
而且html文件很简单
<a href="javascript:" class="{{ classes }}" (click)="onAClick()">{{ content }}</a>
To use it
使用它
<a-external [href]="http://www.foobar.com" [class]="'btn btn-info'" [content]="'The content inside a element'"></a-external>
回答by ConnorsFan
For links to other views of your Angular application, you can implement a CanDeactivate route guard. You will find an example in this stackblitz, for the "Home" page.
对于指向 Angular 应用程序其他视图的链接,您可以实现CanDeactivate 路由保护。您将在此 stackblitz 中找到“主页”页面的示例。
The links that navigate outside of the application should trigger the event handler bound to window:beforeunload
(shown in HomeViewComponent below). However, its behavior seems to be different in Firefox (a confirmation box is shown) and in Chrome (no confirmation box shown). That event cannot be tested with stackblitz, as far as I can see.
在应用程序外部导航的链接应触发绑定到的事件处理程序window:beforeunload
(如下面的 HomeViewComponent 所示)。但是,它的行为在 Firefox(显示确认框)和 Chrome(未显示确认框)中似乎不同。据我所知,该事件无法使用 stackblitz 进行测试。
In app.module:
在 app.module 中:
...
import { AppRoutingModule } from './app.routing.module';
import { DeactivateGuard } from './views/home/deactivate-guard';
@NgModule({
imports: [
AppRoutingModule,
...
],
providers: [
DeactivateGuard
],
...
})
In app.routing.module:
在 app.routing.module 中:
...
import { RouterModule } from '@angular/router';
import { DeactivateGuard } from './views/home/deactivate-guard';
@NgModule({
imports: [
RouterModule.forRoot([
...
{
path: 'home',
component: HomeViewComponent,
canDeactivate: [DeactivateGuard]
},
...
])
],
exports: [
RouterModule,
],
...
})
In home/deactivate-guard:
在家庭/停用警卫:
import { CanDeactivate } from '@angular/router';
import { HomeViewComponent } from './home.component';
export class DeactivateGuard implements CanDeactivate<HomeViewComponent> {
canDeactivate(component: HomeViewComponent) {
return component.canDeactivate();
}
}
In home.component:
在 home.component 中:
import { Component, HostListener } from '@angular/core';
...
@Component({
...
})
export class HomeViewComponent {
@HostListener("window:beforeunload", ["$event"]) unloadHandler(event: Event) {
event.returnValue = false;
}
canDeactivate() {
return confirm("Do you want to leave?");
}
...
}
回答by manish kumar
so Angular provides canActivate to make sure if you want to activate the route or not based on certain condition. You can
所以 Angular 提供了 canActivate 来确定你是否想根据特定条件激活路由。你可以
const routes: Routes = [
{path: '/some-path', canActivate:[AuthGuard]}
];
Your canActivate service
您可以激活服务
import { Injectable } from '@angular/core';
import { CanActivate, CanActivateChild } from '@angular/router';
@Injectable()
export class AuthGuard implements CanActivate, CanActivateChild {
canActivate() {
//ask if he really wants to route.
console.log('i am checking to see if you are logged ')
return true;
}
canActivateChild() {
console.log('checking child route access');
return true;
}
}
In the canActivate you can display a generic model to ask whether he wants to route to URL or not, and based on that you can control which link can have it and which not. You can even write logic for all the routing whether it be coming from anchor tag or anything else.
在 canActivate 中,您可以显示一个通用模型来询问他是否要路由到 URL,并基于此您可以控制哪些链接可以拥有,哪些不可以。您甚至可以为所有路由编写逻辑,无论它来自锚标记还是其他任何东西。
回答by Mohsin Hasan
You can implement route guard which checks for your condition and then decide whether to redirect to clicked url or not depending upon your choice.
您可以实现检查您的条件的路由保护,然后根据您的选择决定是否重定向到点击的 url。
If you are following angular cli then you can simply install route guard by running :
如果您遵循 angular cli,那么您只需运行以下命令即可安装路由防护:
ng g guard my-new-guard
Import guard file in app.module.ts and add it into providers array. In routing file add route guard to the paths on which you want to check for the condition. Like :
在 app.module.ts 中导入保护文件并将其添加到 providers 数组中。在路由文件中,将路由保护添加到要检查条件的路径。喜欢 :
const appRoutes: Routes = [
{path: '/your-path', canActivate: [route-guard]}
];
In your route-guard file you can implement your logic like this :
在你的路由保护文件中,你可以像这样实现你的逻辑:
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class AuthGuardGuard implements CanActivate {
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
if(!state.url.startsWith('/')){
// I have check here for starting single slash for all your angular local routes. You can also check for http or https whichever you want according to your need
// here you can trigger your modal pop-up on its 'OK' button return true to redirect to the url
return true; // or return false on 'Cancel' button of modal pop-up for cancelling route if condition doesn't fullfill
}
}
}
回答by vijayliebe
In .ts File
在 .ts 文件中
ngAfterViewInit() {
var aElements = this._elementRef.nativeElement.querySelectorAll('a');
var aElementsLen = aElements.length;
console.log('aElements==========>', aElements);
for(let i=0; i< aElementsLen; i++){
console.log('aElements[i]==========>', aElements[i]);
aElements[i].addEventListener('click', function(e){
e.preventDefault();
//return true; // If Redirect inside of Angular app
return false; // Redirect outside of Angular app and show popup
});
}
}
回答by Arun Kumaresh
Try this
试试这个
In html
在 html 中
<a role="button" (click)="yourfunc()">
In your ts
在你的 ts
yourfunc(){
alert('navigate')
window.location.href='http://www.somewhere.com';
// your code to navigate
}