有条件地应用指令


109

我正在使用Material 2添加md-raised-button。我只想在某些条件为真时才应用此指令。

例如:

<button md-raised-button="true"></button>

另一个例子:我在plunker中创建了一个基本的动态反应形式。我正在使用formArrayName反应形式的指令用于控件数组。我只想formArrayName在特定条件为真时应用指令,否则不要添加formArrayName指令。

这是一个矮胖的链接


是MD-高架按钮,它是属性指令(material.angular.io/components/component/button
user2899728

在使用指令的条件上应用条件可能会使AoT失效,因为除非应用程序正在运行,否则您将无法编译模板。
Reactgular

Answers:


54

我不知道您是否可以根据条件应用指令,但是一种解决方法是让2个按钮根据条件显示它们

<button *ngIf="!condition"></button>
<button *ngIf="condition" md-raised-button></button> 

编辑:也许会有所帮助。


13
感谢您的答复。但是我已经在问题详细说明的示例中使用了此技术。如果代码很复杂,这是个好选择,但不是个好主意。因为因为这种技术破坏了重用的概念。您可以在plunker中看到我的示例,并注意到由于这种方法我的代码是如何重复的。这就是为什么我不想使用这种技术的原因。我想要一些更好的解决方案,以便可以生成动态元素。
user2899728

1
我懂了。您可以包装在组件中重复的代码。
学士

3
这是个好主意,但不幸的是,在反应形式下它不起作用。对于反应形式,会出现另一个问题。如果我将输入放到单独的组件中,则angular也需要我在该子组件中添加[formGroup] =“ form”。但是,如果这样做,我的数组绑定将无法工作。
user2899728

15
这是一个非常糟糕的解决方案,因为它重复了代码。想象一下,它不仅是按钮,而且是一个div,其中包含很多html代码。
沙迦·哈舒夫(Shachar Har-Shuv),

87

如果仅需要添加属性以触发CSS规则,则可以使用以下方法:(这不会动态创建/销毁指令)

<button [attr.md-raised-button]="condition ? '' : null"></button>

将同样的方法应用到您的矮人:叉子

更新:

condition ? '' : null价值如何运作:

当其空字符串('')变为attr.md-raised-button=""时,其null属性将不存在。

更新: punker更新:fork(版本问题已修复,请注意,该问题最初是基于angular 4的)


@Luke是的,如果您用“(现在)”指的是:自2017 年1月6日起,距提出问题的时间还有5个月了。参见角度变化记录第六项
Aldracor

@Aldracor角5.2.1,不起作用。而且我不明白为什么它应该看起来像“ condition?:null”,而这两个结果基本上都是假的。应该用什么代替“?”?'true'也不起作用。
Arsenii Fomin's

1
因此,对于不想创建html元素以使其指令正常工作并使用ng-container的任何人,我只是传递了[enabled] =“ booleanVar”
Ben Taliadoros

7
在Angular 6中对我不起作用。punker示例不会超过加载屏幕。根据我的阅读,这种方法可能适用于HTML属性,但不适用于Angular指令。最初的问题是关于ng材质库中的Angular Directives。
JeffryHouser

6
@kbpontius感谢您的评论,它适用于HTML属性,但不适用于角度指令(作为属性)
Reza

19

如前所述,这似乎是不可能的。至少可以防止重复的一件事是ng-template。这使您可以提取受ngIf分支影响的元素的内容。

例如,如果要使用Angular Material创建分层菜单组件:

<!-- Button contents -->
<ng-template #contentTemplate>
    <mat-icon *ngIf="item.icon != null">{{ item.icon }}</mat-icon>
    {{ item.label }}
</ng-template>

<!-- Leaf button -->
<button *ngIf="item.children == null" mat-menu-item
    (click)="executeCommand()"
    [disabled]="enabled == false">
    <ng-container *ngTemplateOutlet="contentTemplate"></ng-container>
</button>
<!-- Node button -->
<ng-container *ngIf="item.children != null">
    <button mat-menu-item
        [matMenuTriggerFor]="subMenu">
        <ng-container *ngTemplateOutlet="contentTemplate"></ng-container>
    </button>

    <mat-menu #subMenu="matMenu">
        <menu-item *ngFor="let child of item.children" [item]="child"></menu-item>
    </mat-menu>
</ng-container>

在这里,有条件应用的伪指令是matMenuTriggerFor,该伪指令仅应应用于带有子项的菜单项。按钮的内容通过插入到两个位置ngTemplateOutlet


6
这是让开发人员使用条件指令以及代码可重用性的唯一答案。
Ravinder Payal

16

这可能会迟到,但是它是一种有条件且可行的,有条理地应用指令的方法。

在指令类中,创建输入变量:

@Input('myDirective') options: any;

应用指令时,请设置输入变量的apply属性:

<div [myDirective] = {apply: someCondition}></div>

在指令的方法中,检查变量this.options.apply并根据条件应用指令逻辑:

ngAfterViewInit(): void {
    if (!this.options.apply) {
        return;
    }

    // directive logic
}

3
这对我不起作用,因为该指令仍然存在于组件中,它仅不执行逻辑。我想有条件地应用该指令的存在,特别是因为有css检查该指令。
Ran Lottem,

您遇到的问题与此处列出的问题不同(有条件地应用此指令)。发表您的问题,人们会为您提供帮助。首先,您可以将指令放在div上,并在ng容器周围加上* ngIf来应用条件。ngIf从DOM中删除div节点,因此它可能起作用。我只是在猜测,您需要使用ppl的代码示例/说明来发布问题,以帮助您。
Tiha

这不是一个好的解决方案。指令仍被初始化。
迪诺

8

正如其他人也指出的那样,directives不能动态应用。

但是,如果您只想将md-button的样式从flat切换为凸起,则此

<button md-button [class.mat-raised-button]="isRaised">Toggle Raised Button</button>

会成功的 柱塞


3

这也可能是一个解决方案:

[md-raised-button]="condition ? 'true' : ''"


它适用于角4,离子3,如下所示:

[color]="condition ? 'primary' : ''"其中condition有一个函数来确定该页面是否为活动页面。整个代码如下所示:

<button *ngFor="let page of ..." [color]="isActivePage(page) ? 'primary' : ''">{{ page.title }}</button>


2

当前,有一种NO方法可以有条件地将指令应用于组件。不支持此指令。您创建的组件可以有条件地添加或删除。

与相同的问题已经创建angular2,因此angular4也应如此。

或者,您可以使用ng-if选择该选项

<button ngIf="!condition"></button>
<button ngIf="condition" md-raised-button></button> 


2

我找不到一个好的现有解决方案,所以我建立了自己的指令来执行此操作。

import { Directive, ElementRef, Input } from '@angular/core';

@Directive({
  selector: '[dynamic-attr]'
})
export class DynamicAttrDirective {
  @Input('dynamic-attr') attr: string;
  private _el: ElementRef;

  constructor(el: ElementRef) {
    this._el = el;
  }

  ngOnInit() {
    if (this.attr === '') return null;
    const node = document.createAttribute(this.attr);
    this._el.nativeElement.setAttributeNode(node);
  }
}

然后你的HTML:

<div dynamic-attr="{{hasMargin: 'margin-left' ? ''}}"></div>


您可以使用@HostBinding('attr.dynamic-attr') @Input('dynamic-attr') attr: string;ngOnInit + ElementRef代替。
pinguinjkeke

2
这不是对如何动态添加指令而不是属性的问题的答案。
克里斯·海恩斯

2

也许会帮助某人。

在下面的示例中,我具有,my-button.component.html并且我希望仅在设置了属性的情况下将*appHasPermission指令应用于。<button>role

<ng-container *ngIf="role; else buttonNoRole" >
  <ng-container *appHasPermission="role">
    <!-- button with *appHasPermission -->
    <ng-template *ngTemplateOutlet="buttonNoRole;"></ng-template>
  </ng-container>
</ng-container>

<ng-template #buttonNoRole>
  <!-- button without *appHasPermission -->
  <button
    mat-raised-button type="button"
    [color]="color"
    [disabled]="disabled"
    [(appClickProgress)]="onClick"
    [key]="progressKey">
    <mat-icon *ngIf="icon">{{ icon }}</mat-icon> {{ label }}
  </button>
</ng-template>

这样,您就不会重复<button>代码。


0

是的,有可能。

带有appActiveAhover指令的html页面:)

  <li routerLinkActive="active" #link1="routerLinkActive">
        <a [appActiveAhover]='link1.isActive?false:true' routerLink="administration" [ngStyle]="{'background':link1.isActive?domaindata.get_color3():none}">
          <i class="fa fa-users fa-lg" aria-hidden="true"></i> Administration</a>
      </li>
      <li  routerLinkActive="active" #link2="routerLinkActive">
        <a [appActiveAhover]='link2.isActive?false:true' routerLink="verkaufsburo" [ngStyle]="{'background':link2.isActive?domaindata.get_color3():none,'color':link2.isActive?color2:none}">
          <i class="fa fa-truck fa-lg" aria-hidden="true"></i> Verkaufsbüro</a>
      </li>
      <li  routerLinkActive="active" #link3="routerLinkActive">
        <a [appActiveAhover]='link3.isActive?false:true' routerLink="preisrechner" [ngStyle]="{'background':link3.isActive?domaindata.get_color3():none}">
          <i class="fa fa-calculator fa-lg" aria-hidden="true" *ngIf="routerLinkActive"></i> Preisrechner</a>
      </li>

指示

@Directive({
  selector: '[appActiveAhover]'
})
export class ActiveAhoverDirective implements OnInit {
  @Input() appActiveAhover:boolean;
  constructor(public el: ElementRef, public renderer: Renderer, public domaindata: DomainnameDataService) {
}

  ngOnInit() {
  }

  @HostListener('mouseover') onMouseOver() {
    if(this.appActiveAhover){
      this.renderer.setElementStyle(this.el.nativeElement, 'color', this.domaindata.domaindata.color2);
    }
  }

  @HostListener('mouseout') onMouseOut() {
    if(this.appActiveAhover){
      this.renderer.setElementStyle(this.el.nativeElement, 'color', 'white');
    }
  }

}

2
作为附带说明,不建议使用Renderer,而应使用Renderer2:alligator.io/angular/using-renderer2
tam.teixeira

0

传递null给指令将其删除!

<button md-raised-button="condition ? true : null"></button>

-1

NgClass

[ngClass]="{ 'mat-raised-button': trueCondition }"

真实情况示例:

this.element === 'Today'

或布尔函数

getTruth()

完整的例子:

  <button [ngClass]="{ 'mat-raised-button': trueCondition }">TEXT</button>

如果要使用默认班级:

  <button [ngClass]="{ 'mat-raised-button': trueCondition, 'default-class': !trueCondition }">TEXT</button>

6
这不是我问的。您正在显示课程示例。我说的是属性指令。
user2899728

@ user2899728不幸的是,没有其他方法可以做到。(您不能将md-raised-button属性设置为false)
Edric

@ user2899728无法有条件地应用指令。我试图用另一种方法(“方法”)为您提供所需的结果(最终结果)。
Moshe

当您提供创造性的选择时,通常可以先添加注释行以描述答案的去向。
bvdb

1
@bvdb谢谢您的客气话。我写作时没有方向,那是一个错误。将来,我希望编辑这篇文章,因为它甚至可以帮助一个人。
Moshe

-1

关于您可以做什么,我有了另一个想法。

您可以将要替换的html作为字符串存储在变量中,然后使用DomSanitizerbypassSecurityTrustHtml方法根据需要从中添加/删除指令。

我没有一个干净的解决方案,但至少您不需要重复代码。


-3

截至2019年1月18日,这就是我在Angular 5及更高版本中有条件地添加指令的方式。我需要基于更改<app-nav>组件的颜色darkMode。页面是否处于暗模式。

这对我有用:

<app-nav [color]="darkMode ? 'orange':'green'"></app-nav>

我希望这可以帮助别人。

编辑

这将根据条件更改属性(颜色)的值。碰巧颜色是使用指令定义的。因此,请阅读此书的任何人都不要感到困惑,这不是有条件地应用指令(即,这意味着根据条件向dom添加或删除指令)


3
在这两种情况下,您仅使用不同的选项(即橙色或绿色)应用指令。这个问题要求完全根据条件忽略指令。
Mojtaba
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.