ディレクティブを条件付きで適用する


109

マテリアル2を使用して追加していmd-raised-buttonます。特定の条件が成立した場合にのみ適用したい。

例えば:

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

別の例:plunkerで基本的な動的反応フォームを作成しました。formArrayNameコントロールの配列に反応型のディレクティブを使用しています。formArrayName特定の条件がtrueになった場合にのみディレクティブを適用し、それ以外の場合はformArrayNameディレクティブを追加しません。

こちらがプランカーリンクです。


はいMD-上げボタンを、それが属性ディレクティブ(あるmaterial.angular.io/components/component/button
user2899728

ディレクティブが使用される条件を適用すると、アプリが実行されていないとテンプレートをコンパイルできないため、AoTが役に立たなくなる可能性があります。
Reactgular 2017

回答:


54

条件に基づいてディレクティブを適用できるかどうかはわかりませんが、回避策2つのボタンを用意して、条件に基づいて表示することです。

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

編集:多分これは役に立つでしょう。


13
ご回答ありがとうございます。しかし、質問の詳細に追加したプランカーの例では、この手法をすでに使用しています。これは良いオプションですが、コードが複雑な場合は良い考えではありません。このテクニックは再利用の概念を台無しにするからです。あなたは私の例をplunkerで見ることができ、このアプローチのために私のコードがどのように複製されているかに気づくことができます。だから私はこのテクニックを使いたくないのです。動的要素を生成できるように、より良い解決策が欲しいのですが。
user2899728 2017年

1
そうですか。コンポーネントに複製されたコードをラップすることができます。
LLL 2017年

3
それは良い考えですが、残念ながら反応型の場合には機能しません。反応型では、別の問題が発生します。入力を別のコンポーネントに入れると、angularはその子コンポーネント内にも[formGroup] = "form"を追加する必要があります。しかし、そうすると、配列のバインドが機能しなくなります。
user2899728 2017年

15
それはコードを複製するので、それはひどく解決策です。ボタンだけではなく、多くのHTMLコードが含まれたdivだと想像してください。
Shachar Har-Shuv

87

CSSルールをトリガーするために属性を追加する必要があるだけの場合は、以下のメソッドを使用できます(これはディレクティブを動的に作成/破棄しません)。

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

同じことをプランカーに適用しました:フォーク

更新:

condition ? '' : null値として機能する方法:

空の文字列('')のattr.md-raised-button=""場合はnull、属性が存在しない場合はになります。

更新: plunker更新:フォーク(バージョンの問題は修正されました。質問は元々角4に基づいていたことに注意してください)


@Lukeはい、「(今)」という意味の場合:2017-01-06以降、質問が行われる5か月前でした。角度変更ログの 6番目のアイテムを参照してください
Aldracor

@Aldracor angular 5.2.1、動作しません。そして、両方の結果が基本的にfalseである "condition? '':null"のように見える理由がイベントでわかりません。''の代わりに何をすべきですか?「true」も機能しません。
Arsenii Fomin

1
そのため、ディレクティブが機能するためにhtml要素を作成する必要がなく、ng-containerを使用している場合は、[enabled] = "booleanVar"を渡しただけです
Ben Taliadoros

7
Angular 6では動作しません。plunkerサンプルがロード画面を通過しません。私の読書に基づいて、このアプローチはHTML属性に対しては機能しますが、Angularディレクティブに対しては機能しません。元の質問は、ngマテリアルライブラリのAngular Directivesに関するものでした。
JeffryHouser 2018

6
@kbpontiusコメントに感謝します。Html属性では機能しますが、(属性としての)角度指令では機能しません
Reza

19

すでに述べたように、これは可能ではないようです。少なくとも一部の重複を防ぐために使用できる1つのことは、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 2017

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に置き、* ngIfを含むng-containerをその周りに置いて、条件を適用することができます。ngIfはDOMからdivノードを削除するため、機能する場合があります。私はただ推測しているだけです。pplのコードサンプル/説明を使用して問題を投稿する必要があります。
ティハ

これは良い解決策ではありません。ディレクティブはまだ初期化されています。
Dino

8

他の人も述べたように、directives動的に適用することはできません。

ただし、単にmd-buttonスタイルをフラットからレイズに切り替えたい場合は、この

<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コンポーネントにディレクティブを条件付きで適用する方法があります。これはサポートされていません。作成したコンポーネントは、条件付きで追加または削除できます。

同じ問題がで既に作成されているため、angular2angular4の場合も同様です。

または、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の代わりにa だけを使用できます。
pinguinjkeke 2018

2
これは、属性ではなくディレクティブを動的に追加する方法であった質問への回答ではありません。
Chris Haines

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 2017年


-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 2017年

@ user2899728残念ながらそれを行う他の方法はありません。(md-raised-button属性をfalseに設定することはできません)
Edric '18年

@ user2899728ディレクティブを条件付きで適用する方法はありません。私はあなたが探していたもの(最終結果)を別のアプローチ(「手段」)であなたに与えることを試みました。
Moshe

クリエイティブな代替案を提供する場合、通常、最初にコメント行を挿入して、回答の方向性を説明します。
bvdb

1
@bvdb親切な言葉をありがとう。指示なしで書いていたのですが、それは間違いでした。将来的には、この投稿を編集して、1人でも役立つようにしたいと思っています。
Moshe

-1

私はあなたが何ができるかについて別のアイデアを得ました。

DomSanitizerのbypassSecurityTrustHtmlメソッドを使用して、置き換えたいhtmlを文字列として変数に格納し、必要に応じてディレクティブを追加または削除できます。

私はきれいな解決策にはなりませんが、少なくともコードを繰り返す必要はありません。


-3

2019年1月18日の時点で、これはAngular 5以降で条件付きでディレクティブを追加した方法です。に<app-nav>基づいてコンポーネントの色を変更する必要がありましたdarkMode。ページがダークモードかどうか。

これは私のために働きました:

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

これが誰かの役に立つことを願っています。

編集する

これは、条件に基づいて属性(色)の値を変更します。ディレクティブを使用して色が定義されている場合があります。したがって、これを読んでいる人は混乱しないでください。これはディレクティブを条件付きで適用するものではありません(つまり、条件に基づいてdomにディレクティブを追加または削除することを意味します)。


3
どちらの場合も、異なるオプション(つまり、オレンジまたは緑)を使用してディレクティブを適用します。質問は、条件に基づいてディレクティブをまったく無視することを求めています。
Mojtaba
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.