【问题标题】:Disabling routerLink with stopImmediatePropagation method使用 stopImmediatePropagation 方法禁用 routerLink
【发布时间】:2019-10-09 09:30:32
【问题描述】:

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

HTML 标记应该尽可能干净

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

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

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

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

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

【问题讨论】:

  • 您可以像任何其他指令一样覆盖routerLink 指令
  • 试试<a [routerLink]="disabled ? 'javascript:void(0)' : 'a' " >a link</a>

标签: javascript angular angular-router preventdefault angular-routerlink


【解决方案1】:

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

您尝试的解决方案不起作用,因为stopImmediatePropagation 旨在防止事件冒泡,而preventDefault 旨在防止此类事件的默认浏览器行为(例如:提交事件将触发@ 987654326@ 请求)。无论哪种情况,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

【讨论】:

    【解决方案2】:

    我不确定我是否完全理解问题在问什么。但是你可以根据 disabled 属性来决定是否渲染routerLink 指令。

    在模板中:

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

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

    在你的组件文件中:

    get isDisabled() {
     return ... // logic for getting element disabled state
    }
    

    【讨论】:

      【解决方案3】:

      根据 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
          ) {}
      
      }
      

      &lt;a [appNameRouterLink]="'someRoute'" [disabled]="true"&gt;True&lt;/a&gt;

      再次感觉有点像解决方法,但我想说它有效地抑制了 routerLink 在没有大量写入的情况下触发,同时将其保持在指令中,因此它不会被绑定到一个组件。

      【讨论】:

        猜你喜欢
        • 2017-09-26
        • 2019-03-31
        • 2011-07-15
        • 2020-09-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多