Wenden Sie eine Richtlinie unter bestimmten Bedingungen an

109

Ich benutze Material 2, um hinzuzufügen md-raised-button. Ich möchte diese Richtlinie nur anwenden, wenn eine bestimmte Bedingung erfüllt ist.

Beispielsweise:

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

Ein weiteres Beispiel: Ich habe im Plunker eine dynamische Grundreaktionsform erstellt. Ich verwende die formArrayNameDirektive der reaktiven Form für eine Reihe von Kontrollen. Ich möchte die formArrayNameDirektive nur anwenden, wenn eine bestimmte Bedingung erfüllt ist, andernfalls keine formArrayNameDirektive hinzufügen .

Hier ist ein Plunker-Link .

user2899728
quelle
Ja, Md-Raised-Button ist eine Attribut-Direktive ( material.angular.io/components/component/button )
user2899728
Das Anwenden von Bedingungen, unter denen Direktiven verwendet werden, würde AoT wahrscheinlich unbrauchbar machen, da Sie die Vorlagen nur kompilieren können, wenn die App ausgeführt wird.
Reactgular

Antworten:

54

Ich weiß nicht, ob Sie Anweisungen basierend auf einer Bedingung anwenden können, aber eine Problemumgehung besteht darin, zwei Schaltflächen zu haben und diese basierend auf einer Bedingung anzuzeigen .

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

Edit: vielleicht dies hilfreich sein.

LLL
quelle
13
Danke für Ihre Antwort. Aber ich habe diese Technik bereits in dem Plunker-Beispiel verwendet, das ich im Detail hinzugefügt habe. Dies ist eine gute Option, aber keine gute Idee, wenn der Code komplex ist. Denn weil diese Technik das Konzept der Wiederverwendung ruiniert. Sie können mein Beispiel im Plunker sehen und feststellen, wie mein Code aufgrund dieses Ansatzes dupliziert wird. Deshalb möchte ich diese Technik nicht anwenden. Ich möchte eine bessere Lösung, mit der ich dynamische Elemente generieren kann.
user2899728
1
Aha. Sie können den Code, der in der Komponente dupliziert ist, umbrechen.
LLL
3
Es ist eine gute Idee, aber leider funktioniert es bei reaktiven Formen nicht. Bei reaktiven Formen tritt ein anderes Problem auf. Wenn ich Eingaben in eine separate Komponente einfüge, muss ich bei Angular auch [formGroup] = "form" in diese untergeordnete Komponente einfügen. Aber wenn ich das tue, würde meine Array-Bindung nicht funktionieren.
user2899728
15
Das ist eine schreckliche Lösung, da es Code dupliziert. Stellen Sie sich vor, es ist nicht nur eine Schaltfläche, sondern ein Div mit viel HTML-Code.
Shachar Har-Shuv
87

Wenn Sie nur ein Attribut hinzufügen müssen, um CSS-Regeln auszulösen, können Sie die folgende Methode verwenden: (Dadurch wird eine Direktive nicht dynamisch erstellt / zerstört.)

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

Gleiches gilt für Ihren Plunker: Gabel

Aktualisieren:

Wie condition ? '' : nullfunktioniert der Wert:

Wenn es die leere Zeichenfolge ( '') ist, wird es attr.md-raised-button="", wenn es nulldas Attribut nicht existiert.

Update: Plunker Update: Gabel (Versionsprobleme behoben, bitte beachten Sie, dass die Frage ursprünglich auf Winkel 4 basierte)

Aldracor
quelle
@ Luke Ja, wenn Sie mit "(jetzt)" meinen als: seit 2017-01-06, was 5 Monate war, bevor die Frage gestellt wurde. siehe eckiges Changelog 6. Punkt
Aldracor
@Aldracor Winkel 5.2.1, funktioniert nicht. Und ich verstehe nicht, warum es wie "Bedingung?" ': Null "aussehen sollte, wobei beide Ergebnisse grundsätzlich falsch sind. Was soll statt '' sein? 'true' funktioniert auch nicht.
Arsenii Fomin
1
Für alle, die kein HTML-Element erstellen möchten, damit ihre Direktive funktioniert, und ng-container verwenden, habe ich einfach ein [enabled] = "booleanVar" übergeben
Ben Taliadoros
7
Funktioniert in Angular 6 nicht für mich. Das Plunker-Sample kommt nicht über den Ladebildschirm hinaus. Basierend auf meiner Lektüre funktioniert dieser Ansatz möglicherweise für HTML-Attribute, jedoch nicht für Angular-Direktiven. Die ursprüngliche Frage betraf Angular Directives aus der ng-Materialbibliothek.
JeffryHouser
6
@kbpontius danke für den Kommentar, es funktioniert auf HTML-Attributen, aber nicht auf eckigen Anweisungen (als Attribut)
Reza
19

Wie bereits erwähnt, scheint dies nicht möglich zu sein. Eine Sache, die verwendet werden kann, um zumindest eine Duplizierung zu verhindern, ist ng-template. Auf diese Weise können Sie den Inhalt des von der ngIfVerzweigung betroffenen Elements extrahieren .

Wenn Sie beispielsweise mit Angular Material eine hierarchische Menükomponente erstellen möchten:

<!-- 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>

Hier gilt die bedingt angewendete Direktive matMenuTriggerFor, die nur auf Menüpunkte mit untergeordneten Elementen angewendet werden soll. Der Inhalt der Schaltfläche wird an beiden Stellen über eingefügt ngTemplateOutlet.

HB
quelle
6
Dies ist die einzige Antwort, mit der ein Entwickler bedingte Anweisungen sowie die Wiederverwendbarkeit von Code verwenden kann.
Ravinder Payal
16

Dies mag spät kommen, ist jedoch eine praktikable und elegante Methode, um eine Richtlinie unter bestimmten Bedingungen anzuwenden.

Erstellen Sie in der Direktivenklasse die Eingabevariable:

@Input('myDirective') options: any;

Legen Sie beim Anwenden der Direktive die Eigenschaft apply der Eingabevariablen fest:

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

Überprüfen Sie in der Methode der Direktive die Variable this.options.apply und wenden Sie die Direktivenlogik basierend auf der Bedingung an:

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

    // directive logic
}
Tiha
quelle
3
Dies funktioniert bei mir nicht, da die Direktive noch in der Komponente vorhanden ist und nur keine Logik ausführt. Ich möchte, dass die Existenz der Richtlinie unter bestimmten Bedingungen gilt, insbesondere weil es CSS gibt, die diese Richtlinie prüfen.
Ran Lottem
Sie haben ein anderes Problem als das hier aufgeführte (wenden Sie die Richtlinie unter bestimmten Bedingungen an). Veröffentlichen Sie Ihr Problem und die Leute werden Ihnen helfen. Als erste Idee könnten Sie die Direktive auf ein div setzen und einen ng-Container mit einem * ngIf darum setzen, um Ihre Bedingung anzuwenden. ngIf entfernt den div-Knoten aus dem DOM, sodass er möglicherweise funktioniert. Ich vermute nur, Sie müssen Ihr Problem mit Codebeispielen / Beschreibung für ppl posten, um Ihnen zu helfen.
Tiha
Dies ist keine gute Lösung. Die Richtlinie wird immer noch initialisiert.
Dino
8

Wie andere ebenfalls angegeben haben, directiveskann nicht dynamisch angewendet werden.

Wenn Sie jedoch nur den md-buttonStil von flach nach erhöht umschalten möchten , dann ist dies der Fall

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

würde den Trick machen. Plunker

Ankit Singh
quelle
3

Dies könnte auch eine Lösung sein:

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


Es funktioniert für Winkel 4, Ion 3 wie folgt:

[color]="condition ? 'primary' : ''"Wo conditionist eine Funktion, die entscheidet, ob dies eine aktive Seite ist oder nicht. Der gesamte Code sieht folgendermaßen aus:

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

zalog
quelle
2

Derzeit gibt es eine NOMöglichkeit, eine Direktive bedingt auf eine Komponente anzuwenden. Dies wird nicht unterstützt. Die von Ihnen erstellten Komponenten können bedingt hinzugefügt oder entfernt werden.

Es gibt bereits ein Problem, das für dasselbe mit erstellt wurde angular2, daher sollte dies auch bei angle4 der Fall sein.

Alternativ können Sie die Option mit ng-if wählen

<button ngIf="!condition"></button>
<button ngIf="condition" md-raised-button></button> 
Sajeetharan
quelle
1
bereits in der Antwort
Sumit Ramteke
2

Ich konnte keine schöne existierende Lösung finden, also habe ich meine eigene Direktive erstellt, die dies tut.

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);
  }
}

Dann dein HTML:

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

Cappi10
quelle
Sie können @HostBinding('attr.dynamic-attr') @Input('dynamic-attr') attr: string;anstelle von ngOnInit + ElementRef nur ein verwenden.
Pinguinjkeke
2
Dies ist keine Antwort auf die Frage, wie eine Direktive dynamisch hinzugefügt werden soll, kein Attribut.
Chris Haines
2

Vielleicht hilft es jemandem.

Im folgenden Beispiel habe ich die my-button.component.htmlund ich möchte die *appHasPermissionDirektive <button>nur dann auf die anwenden , wenn das roleAttribut gesetzt ist.

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

Auf diese Weise duplizieren Sie den <button>Code nicht.

MhagnumDw
quelle
0

Ja, es ist möglich.

HTML-Seite mit AppActiveAhover-Direktive :)

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

Richtlinie

@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');
    }
  }

}
Chaitanya Nekkalapudi
quelle
2
Als Randnotiz ist der Renderer veraltet, verwenden Sie stattdessen Renderer2: alligator.io/angular/using-renderer2
tam.teixeira
0

Durch nulldie Verabschiedung der Richtlinie wird sie entfernt!

<button md-raised-button="condition ? true : null"></button>
Yogesh Aggarwal
quelle
-1

Verwenden NgClass

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

Beispiel für einen wahren Zustand:

this.element === 'Today'

oder eine boolesche Funktion

getTruth()

vollständiges Beispiel:

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

Wenn Sie eine Standardklasse möchten:

  <button [ngClass]="{ 'mat-raised-button': trueCondition, 'default-class': !trueCondition }">TEXT</button>
Moshe
quelle
6
Das habe ich nicht gefragt. Sie zeigen ein Beispiel für eine Klasse. Ich spreche von Attribut-Direktive.
user2899728
@ user2899728 Leider gibt es keine andere Möglichkeit, dies zu tun. (Sie können md-raised-buttonAttribut nicht als falsch setzen)
Edric
@ user2899728 Es gibt keine Möglichkeit, Anweisungen bedingt anzuwenden. Ich habe versucht, Ihnen mit einem anderen Ansatz (dem "Mittel") das zu geben, wonach Sie gesucht haben (Endergebnis).
Moshe
Wenn Sie eine kreative Alternative anbieten, ist es normalerweise hilfreich, zuerst eine Reihe von Kommentaren einzugeben, um zu beschreiben, wohin Sie mit Ihrer Antwort gehen.
Bvdb
1
@bvdb danke für deine freundlichen Worte. Ich habe ohne Anweisung geschrieben, und das war ein Fehler. Ich hoffe, dass ich diesen Beitrag in Zukunft bearbeiten kann, da er sogar einer Person helfen könnte.
Moshe
-1

Ich habe eine andere Idee, was Sie tun könnten.

Sie können das HTML, das Sie ersetzen möchten, in einer Variablen als Zeichenfolge speichern und dann die Direktive mithilfe der bypassSecurityTrustHtmlMethode des DomSanitizer nach Belieben hinzufügen / entfernen .

Ich habe keine saubere Lösung, aber zumindest müssen Sie den Code nicht wiederholen.

LLL
quelle
-3

Zum 18. Januar 2019 habe ich auf diese Weise eine Direktive in Angular 5 und höher unter bestimmten Bedingungen hinzugefügt. Ich musste die Farbe der <app-nav>Komponente basierend auf ändern darkMode. Ob sich die Seite im dunklen Modus befand oder nicht.

Das hat bei mir funktioniert:

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

Ich hoffe das hilft jemandem.

BEARBEITEN

Dies ändert den Wert eines Attributs (Farbe) basierend auf einer Bedingung. Es kommt einfach vor, dass die Farbe mithilfe einer Direktive definiert wird. Wenn Sie dies lesen, werden Sie bitte nicht verwirrt. Dies gilt nicht für eine bedingte Anweisung (dh das Hinzufügen oder Entfernen einer Anweisung zum Dom basierend auf einer Bedingung).

Sandra Israel
quelle
3
Sie wenden die Richtlinie in beiden Fällen nur mit unterschiedlichen Optionen an (z. B. orange oder grün). In der Frage wird darum gebeten, die Richtlinie aufgrund einer Bedingung überhaupt zu ignorieren.
Mojtaba