7

任务 - 为 Angular 库创建一个可重用的按钮/锚标记属性选择组件,其中尽可能多的行为逻辑绑定在组件本身而不是 HTML 标记上。

理想情况下,HTML 标记应尽可能干净

<a routerLink="" attributeSelectorForComponent></a>

问题 - 尝试通过单击侦听器阻止 routerLink[attr.disabled]在锚标记上出现时触发。

  @HostListener('click', ['$event']) onMouseClick(event: Event) {
    event.stopImmediatePropagation();
    event.preventDefault()
  }

为简单起见,从等式中删除了禁用的逻辑,无论如何仍会触发 routerLink。

建议的解决方案 -如何有条件地禁用 routerLink 属性?并不能真正帮助解决我的问题,禁用指针事件只会禁用鼠标事件而不是键盘事件,并且还会阻止我删除指针事件:鼠标悬停时没有,单击等需要相对复杂的检测禁用属性并相应地删除 css 的解决方案,通常看起来更像是一个 hacky 解决方案而不是正确的解决方案。

4

3 回答 3

3

没有会导致这种标记的解决方案<a routerLink="" attributeSelectorForComponent></a>

您尝试的解决方案不起作用,因为stopImmediatePropagation旨在防止事件冒泡,并且preventDefault旨在防止此类事件的默认浏览器行为(例如:提交事件将触发POST请求)。在任何一种情况下,Angular 都会收到该事件的通知并做出相应的反应。

RouterLink如果指令具有exportAs属性,则可能有一个干净的解决方案。在这种情况下,可以通过RouterLink自定义指令来控制。不幸的是,事实并非如此(RouterLink 来源

剩下的唯一选择是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

于 2019-10-12T09:41:28.993 回答
0

我不确定我是否完全理解问题所在。但是您可以routerLink根据 disabled 属性决定是否呈现指令。

在模板中:

<a [attr.routerLink]="isDisabled ? null : ''" attributeSelectorForComponent></a>

其中 disable 是元素上 disabled 属性的当前状态。当值为 时null,该routerLink指令将不会在元素上呈现。

在您的组件文件中:

get isDisabled() {
 return ... // logic for getting element disabled state
}
于 2019-10-12T12:34:50.560 回答
0

根据 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 在没有大量写入的情况下触发,同时将其保持在指令中,因此它不会被绑定到一个组件。

于 2019-10-17T14:55:23.937 回答