dynamically - conditionally add attribute angular




Apply a directive conditionally (8)

I am using Material 2 to add md-raised-button .

I want to apply this directive only if certain condition becomes true.

For example:

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

Another example: I created a basic dynamic reactive form in plunker. I am using formArrayName directive of reactive form for array of controls. I want to apply formArrayName directive only if specific condition becomes true. otherwise don't add formArrayName directive. I tried and researched a lot but could find any solution.

Here is plunker link: https://plnkr.co/edit/oPZ7PyBSf8jjYa2KVh4J?p=preview

I would really appreciate any contribution.

Thanks in advance!


As already noted this does not appear to be possible. One thing that can be used to at least prevent some duplication is ng-template . This allows you to extract the content of the element affected by the ngIf branching.

If you for example want to create a hierarchical menu component using 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>

Here the conditionally applied directive is matMenuTriggerFor , which should only be applied to menu items with children. The contents of the button are inserted in both places via ngTemplateOutlet .


As at 18th Jan 2019, This is how I added a directive conditionally in Angular 5 and above. I needed to change the color of the <app-nav> component based on darkMode . If the page was in dark mode or not.

This worked for me:

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

I hope this helps someone.

EDIT

This changes the value of an attribute (color) based on a condition. It just happens that the color is defined using a directive. So anyone reading this please do not get confused, this is not applying a directive conditionally (ie. which means adding or removing a directive to the dom based on a condition)


Currently, there is NO way to conditionally apply a directive to a component.This is not supported.The components which you have created can be added or removed conditionally.

There is already an issue created for the same with angular2 , so it should be the case with angular4 aswell.

Alternatively you can go for the option with ng-if

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

I couldn't find a nice existing solution, so i built my own directive which does this.

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

Then your html:

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


I got another idea about what you could do.

You could store the html you want replaced in a variable as a string and then add / remove the directive from it as you wish, using the bypassSecurityTrustHtml method of the DomSanitizer .

I doesn't result in a clean solution but at least you don't need to repeat the code.


This could be a solution too:

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

It's working for angular 4, ionic 3 like this:

[color]="condition ? 'primary' : ''" where condition is a function that decides if this is an active page or not. The whole code look like this:

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


Use NgClass

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

example of true condition:

this.element === 'Today'

or a boolean function

getTruth()

full example:

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

If you want a default class:

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

You can use the below method:

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

Applied the same to your plunker: fork

Update:

How condition ? '' : null works as the value:

When its the empty string ( '' ) it becomes attr.md-raised-button="" , when its null the attribute will not exist.

Update: plunker update: fork (version issues fixed, please note the question was originally based on angular 4)





angular-material2