使用 stopImmediatePropagation 方法禁用 routerLink
Disabling routerLink with stopImmediatePropagation method
任务 - 为 Angular 库创建一个可重复使用的 button/anchor 标记属性选定组件,其中尽可能多的行为逻辑绑定在组件本身而不是 HTML 标记。
HTML 理想情况下标记应尽可能干净
<a routerLink="" attributeSelectorForComponent></a>
问题 - 当 [attr.disabled]
出现在锚标记上时,试图阻止 routerLink 使用点击侦听器触发。
@HostListener('click', ['$event']) onMouseClick(event: Event) {
event.stopImmediatePropagation();
event.preventDefault()
}
为了简单起见,从等式中删除了禁用的逻辑,无论如何 routerLink 仍然被触发。
建议的解决方案 - 并没有真正帮助解决我的问题,禁用指针事件只会禁用鼠标事件而不是键盘事件,并且还会阻止我删除指针事件:none 用鼠标悬停,点击 ect 需要一个相对复杂的解决方案来检测禁用属性并相应地删除 css,并且通常看起来更像是一个 hacky 解决方案而不是正确的解决方案。
没有解决方案会导致此标记 <a routerLink="" attributeSelectorForComponent></a>
。
您尝试的解决方案将不起作用,因为 stopImmediatePropagation
旨在防止事件冒泡,而 preventDefault
旨在防止此类事件的默认浏览器行为(例如:提交事件将触发 POST
请求)。无论哪种情况,Angular 都会收到事件通知并做出相应反应。
如果 RouterLink
指令具有 exportAs
属性,则可能会有一个干净的解决方案。在这种情况下,可以通过自定义指令控制 RouterLink
。不幸的是,情况并非如此 (RouterLink source)
剩下的唯一选择是像这样扩展 RouterLinkWithHref
指令:
@Directive({
selector: "a[myRouterLink],area[myRouterLink]"
})
export class MyDirective extends RouterLinkWithHref implements OnChanges {
@Input()
myRouterLink;
@Input()
myDisabled;
constructor(
private myRouter: Router,
private myRoute: ActivatedRoute,
private myLocationStrategy: LocationStrategy,
private host: ElementRef
) {
super(myRouter, myRoute, myLocationStrategy);
}
ngOnChanges() {
if (this.myDisabled) {
this.host.nativeElement.setAttribute("disabled", "disabled");
this.routerLink = null;
} else {
this.host.nativeElement.removeAttribute("disabled");
this.routerLink = this.myRouterLink;
}
}
}
这给出了以下标记:<a myRouterLink="a" [myDisabled]="disabled"></a>
请注意,对于完整的工作解决方案,您还必须扩展 RouterLink
您可以在此处试用演示:https://stackblitz.com/edit/angular-p2w4ff
我不确定我是否完全理解问题的含义。但是你可以根据disabled属性决定是否渲染routerLink
指令。
在模板中:
<a [attr.routerLink]="isDisabled ? null : ''" attributeSelectorForComponent></a>
禁用是元素上禁用属性的当前状态。当值为 null
时,routerLink
指令将不会在元素上呈现。
在您的组件文件中:
get isDisabled() {
return ... // logic for getting element disabled state
}
根据 Twisting Nethers 的建议,我制定了我认为更简单的指令来处理该问题。
import { Directive, Input, HostListener } from '@angular/core';
import { Router } from '@angular/router';
@Directive({
selector: 'a[appNameRouterLink]'
})
export class DisableRouterDirective {
@Input() appNameRouterLink: string;
@Input() disabled: boolean;
@HostListener('click')
disableOrEnableRouterNavigation() {
if (this.disabled && this.disabled === true) {
return;
} else {
this.router.navigate([this.appNameRouterLink]);
}
}
constructor(
private router: Router
) {}
}
<a [appNameRouterLink]="'someRoute'" [disabled]="true">True</a>
再次感觉有点变通,但我想说它有效地抑制了 routerLink 在没有大量写入的情况下触发,同时将它保持在一个指令中,因此它不会被绑定到一个组件。
任务 - 为 Angular 库创建一个可重复使用的 button/anchor 标记属性选定组件,其中尽可能多的行为逻辑绑定在组件本身而不是 HTML 标记。
HTML 理想情况下标记应尽可能干净
<a routerLink="" attributeSelectorForComponent></a>
问题 - 当 [attr.disabled]
出现在锚标记上时,试图阻止 routerLink 使用点击侦听器触发。
@HostListener('click', ['$event']) onMouseClick(event: Event) {
event.stopImmediatePropagation();
event.preventDefault()
}
为了简单起见,从等式中删除了禁用的逻辑,无论如何 routerLink 仍然被触发。
建议的解决方案 -
没有解决方案会导致此标记 <a routerLink="" attributeSelectorForComponent></a>
。
您尝试的解决方案将不起作用,因为 stopImmediatePropagation
旨在防止事件冒泡,而 preventDefault
旨在防止此类事件的默认浏览器行为(例如:提交事件将触发 POST
请求)。无论哪种情况,Angular 都会收到事件通知并做出相应反应。
如果 RouterLink
指令具有 exportAs
属性,则可能会有一个干净的解决方案。在这种情况下,可以通过自定义指令控制 RouterLink
。不幸的是,情况并非如此 (RouterLink source)
剩下的唯一选择是像这样扩展 RouterLinkWithHref
指令:
@Directive({
selector: "a[myRouterLink],area[myRouterLink]"
})
export class MyDirective extends RouterLinkWithHref implements OnChanges {
@Input()
myRouterLink;
@Input()
myDisabled;
constructor(
private myRouter: Router,
private myRoute: ActivatedRoute,
private myLocationStrategy: LocationStrategy,
private host: ElementRef
) {
super(myRouter, myRoute, myLocationStrategy);
}
ngOnChanges() {
if (this.myDisabled) {
this.host.nativeElement.setAttribute("disabled", "disabled");
this.routerLink = null;
} else {
this.host.nativeElement.removeAttribute("disabled");
this.routerLink = this.myRouterLink;
}
}
}
这给出了以下标记:<a myRouterLink="a" [myDisabled]="disabled"></a>
请注意,对于完整的工作解决方案,您还必须扩展 RouterLink
您可以在此处试用演示:https://stackblitz.com/edit/angular-p2w4ff
我不确定我是否完全理解问题的含义。但是你可以根据disabled属性决定是否渲染routerLink
指令。
在模板中:
<a [attr.routerLink]="isDisabled ? null : ''" attributeSelectorForComponent></a>
禁用是元素上禁用属性的当前状态。当值为 null
时,routerLink
指令将不会在元素上呈现。
在您的组件文件中:
get isDisabled() {
return ... // logic for getting element disabled state
}
根据 Twisting Nethers 的建议,我制定了我认为更简单的指令来处理该问题。
import { Directive, Input, HostListener } from '@angular/core';
import { Router } from '@angular/router';
@Directive({
selector: 'a[appNameRouterLink]'
})
export class DisableRouterDirective {
@Input() appNameRouterLink: string;
@Input() disabled: boolean;
@HostListener('click')
disableOrEnableRouterNavigation() {
if (this.disabled && this.disabled === true) {
return;
} else {
this.router.navigate([this.appNameRouterLink]);
}
}
constructor(
private router: Router
) {}
}
<a [appNameRouterLink]="'someRoute'" [disabled]="true">True</a>
再次感觉有点变通,但我想说它有效地抑制了 routerLink 在没有大量写入的情况下触发,同时将它保持在一个指令中,因此它不会被绑定到一个组件。