【问题标题】:In Angular 2+, can I detect when a directive (like routerLink) is applied to my custom component?在 Angular 2+ 中,我可以检测何时将指令(如 routerLink)应用于我的自定义组件吗?
【发布时间】:2018-02-26 20:28:53
【问题描述】:

我有一个自定义按钮组件,像这样(简化):

@Component({
    selector: 'my-button',
    template: `
        <button (click)="handleClick($event)">
            <ng-content></ng-content>
        </button>
    `
})
export class MyButtonComponent {
    @Output() public onClick: EventEmitter<Event> = new EventEmitter();

    handleClick(e) {
        this.onClick.emit(e);
    }
}

按钮的正常用例是用户附加onClick 处理程序。但是,有些用户会希望将按钮用作链接,如下所示:

<my-button [routerLink]="'/dashboard'">Go to dashboard</my-button>

在这种情况下,我想做的是将my-button 渲染为&lt;a&gt; 元素,而不是文字&lt;button&gt;。但为了做到这一点,我需要检测到用户已将[routerLink] 指令附加到它。

有什么办法吗?

我知道我可以添加一个布尔值 @Input() 属性,将渲染切换到 &lt;a&gt; 模式,但这感觉很笨重。

【问题讨论】:

  • 无论哪种方式,您都必须使用@Input(),对于RouterLink
  • 你是什么意思,@12 秒?我现在不使用它,并且链接有效。
  • 抱歉,我没有导入 RouteModule。我将就如何实现这一点添加我的答案。

标签: javascript angular


【解决方案1】:

您必须使用@Optional@Host 两者都位于@angular/core

在您的my-button 打字稿组件上,您需要像这样进行依赖注入:

export class MyButtonComponent implements OnInit {
  constructor(@Optional() @Host() routerLink: RouterLink) {
     console.log(routerLink)
  }
  ...
}

然后在您的模板上,您可以检查routerLink 是否为空,并呈现&lt;a&gt; 标签或&lt;button&gt; 标签

编辑:

要使链接正常工作,您需要这样做:

<a [routerLink]="routerLink.commands">
   Test
</a> 

很遗憾,由于某种原因,我无法让&lt;ng-content&gt;a 标签中工作。

编辑 2: ng-content 不起作用的原因是组件中有多个ng-content,解决此问题的一种方法是使用 ng-template,例如:

<ng-container *ngIf="hasRouterLink">
  <a [routerLink]="routerLink.commands">
    <ng-container *ngTemplateOutlet="contentTpl"></ng-container>
  </a> 
</ng-container>


<ng-container *ngIf="!hasRouterLink">
  <button>
    <ng-container *ngTemplateOutlet="contentTpl"></ng-container> 
  </button> 
</ng-container>

<ng-template #contentTpl><ng-content></ng-content></ng-template>

【讨论】:

  • 这行得通。不幸的是,事实证明我不能用它来实现我想要的(即创建一个像链接一样的链接),但它确实让我在组件内获得了路由器链接实例。
  • @panta82,请检查我的编辑,了解如何创建链接。为此创建了 stackblitz:stackblitz.com/edit/angular-ztvtpx
  • @panta82,另一个更新,仅供参考,说明如何解决多个ng-content 问题。
  • 是的,我也成功了。做得好。几个问题。 1) Typescript 抱怨 commands 是私有财产。 2) 您现在有 2 个链接,一个用于顶部组件,一个用于内部。 3) 如果您添加任何其他 routerLink 参数(如 replaceUrl),则不会应用它们
  • 我在做&lt;ng-container [ngTemplateOutlet]&gt;,在那里我定义了一个包含ng-content 的模板,它似乎也可以工作。
【解决方案2】:

您是否打算像ng-content 那样添加比文字更大的内容,否则onClick 会有一些复杂的逻辑? 我认为您的情况很常见,通常可以通过创建 css 类来使按钮和链接看起来相同来解决。您可以根据情况使用&lt;a&gt;&lt;button&gt;,只需添加必要的类

【讨论】:

  • 实际上,ng-content 周围还有更多的东西,比如微调器和图标。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-08
  • 1970-01-01
  • 2017-10-27
  • 2018-06-14
  • 2018-02-23
  • 1970-01-01
  • 2011-02-20
相关资源
最近更新 更多