有条件地应用指令
Apply a directive conditionally
我正在使用 Material 2 添加 md-raised-button
。我只想在特定条件成立时应用此指令。
例如:
<button md-raised-button="true"></button>
另一个例子:
我在 plunker 中创建了一个基本的动态反应形式。
我正在为控件数组使用反应形式的 formArrayName
指令。
我只想在特定条件为真时应用 formArrayName
指令,否则不要添加 formArrayName
指令。
这里是plunker link.
使用NgClass
[ngClass]="{ 'mat-raised-button': trueCondition }"
真实条件示例:
this.element === 'Today'
或布尔函数
getTruth()
完整示例:
<button [ngClass]="{ 'mat-raised-button': trueCondition }">TEXT</button>
如果你想要一个默认的 class:
<button [ngClass]="{ 'mat-raised-button': trueCondition, 'default-class': !trueCondition }">TEXT</button>
我不知道您是否可以根据条件应用指令,但是 解决方法 将具有 2 个按钮并根据条件显示它们.
<button *ngIf="!condition"></button>
<button *ngIf="condition" md-raised-button></button>
编辑:也许 this 会有帮助。
目前,有 NO
方法有条件地将指令应用于 component.This 不是 supported.The 您创建的组件可以有条件地添加或删除。
已经为 angular2
创建了一个问题,因此 angular4 也应该如此。
或者你可以选择 ng-if
<button ngIf="!condition"></button>
<button ngIf="condition" md-raised-button></button>
正如其他人所说,directives
无法动态应用。
但是,如果您只想将 md-button
的样式从 flat 切换为 raised,那么这个
<button md-button [class.mat-raised-button]="isRaised">Toggle Raised Button</button>
就可以了。 Plunker
我对你能做什么有了另一个想法。
您可以将要替换的 html 作为字符串存储在变量中,然后使用 [=11= 的 bypassSecurityTrustHtml
方法根据需要添加/删除指令].
我没有得到一个干净的解决方案,但至少你不需要重复代码。
这也可能是一个解决方案:
[md-raised-button]="condition ? 'true' : ''"
它适用于 angular 4,离子 3,如下所示:
[color]="condition ? 'primary' : ''"
其中 condition
是一个决定这是否是活动页面的函数。整个代码如下所示:
<button *ngFor="let page of ..." [color]="isActivePage(page) ? 'primary' : ''">{{ page.title }}</button>
如果你只需要添加一个属性来触发CSS规则,你可以使用下面的方法:(这不会动态地create/destroy一个指令)
<button [attr.md-raised-button]="condition ? '' : null"></button>
对你的 plunker 应用相同的方法:fork
更新:
condition ? '' : null
如何作为值:
当它是空字符串(''
)时它变成attr.md-raised-button=""
,当它的null
属性将不存在。
更新: plunker更新:fork(版本问题已修复,请注意问题最初是基于angular 4)
是的,这是可能的。
html 带有 appActiveAhover 指令的页面 :)
<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');
}
}
}
如前所述,这似乎是不可能的。至少可以用来防止某些重复的一件事是 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
.
插入到两个地方
这可能来晚了,但它是一种有条件地应用指令的可行且优雅的方法。
在指令 class 中创建输入变量:
@Input('myDirective') options: any;
应用指令时,设置输入变量的应用属性:
<div [myDirective] = {apply: someCondition}></div>
在指令方法中检查变量 this.options.apply 并根据条件应用指令逻辑:
ngAfterViewInit(): void {
if (!this.options.apply) {
return;
}
// directive logic
}
我找不到一个很好的现有解决方案,所以我构建了自己的指令来执行此操作。
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>
截至 2019 年 1 月 18 日,
这就是我在 Angular 5 及更高版本中有条件地添加指令的方式。我需要根据 darkMode
更改 <app-nav>
组件的颜色。页面是否处于深色模式。
这对我有用:
<app-nav [color]="darkMode ? 'orange':'green'"></app-nav>
我希望这对某人有所帮助。
编辑
这会根据条件更改属性(颜色)的值。碰巧颜色是使用指令定义的。所以任何阅读本文的人请不要感到困惑,这不是有条件地应用指令(即,这意味着根据条件向 dom 添加或删除指令)
也许它会对某人有所帮助。
在下面的示例中,我有 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>
代码。
将 null
传递给指令将其删除!
<button md-raised-button="condition ? true : null"></button>
我正在使用 Angular Material
,在 *ngIf
上添加一个元素对我来说效果不佳(该元素会在许多新生成的 material HTML 中消失标签哈哈)。
我不知道这是否是一个好习惯,但我使用了 OnChanges
并且我有一种条件指令 - 它起作用了! :)
我就是这样解决的:
import { Directive, Renderer2, ElementRef, Input, OnChanges, SimpleChanges, AfterViewInit } from '@angular/core';
@Directive({
selector: '[appDirtyInputIndicator]'
})
export class DirtyInputIndicatorDirective implements OnChanges, AfterViewInit {
@Input('appDirtyInputIndicator') dirtyInputIndicator: boolean;
span = this.renderer.createElement('span');
constructor(private renderer: Renderer2, private el: ElementRef) {}
ngOnChanges(changes: SimpleChanges): void {
if (changes.dirtyInputIndicator && this.dirtyInputIndicator) {
this.renderer.appendChild(this.el.nativeElement, this.span);
} else {
this.renderer.removeChild(this.el.nativeElement, this.span);
}
}
ngAfterViewInit() {
this.renderer.addClass(this.span, 'dirty_input_badge');
}
}
我正在使用 Material 2 添加 md-raised-button
。我只想在特定条件成立时应用此指令。
例如:
<button md-raised-button="true"></button>
另一个例子:
我在 plunker 中创建了一个基本的动态反应形式。
我正在为控件数组使用反应形式的 formArrayName
指令。
我只想在特定条件为真时应用 formArrayName
指令,否则不要添加 formArrayName
指令。
这里是plunker link.
使用NgClass
[ngClass]="{ 'mat-raised-button': trueCondition }"
真实条件示例:
this.element === 'Today'
或布尔函数
getTruth()
完整示例:
<button [ngClass]="{ 'mat-raised-button': trueCondition }">TEXT</button>
如果你想要一个默认的 class:
<button [ngClass]="{ 'mat-raised-button': trueCondition, 'default-class': !trueCondition }">TEXT</button>
我不知道您是否可以根据条件应用指令,但是 解决方法 将具有 2 个按钮并根据条件显示它们.
<button *ngIf="!condition"></button>
<button *ngIf="condition" md-raised-button></button>
编辑:也许 this 会有帮助。
目前,有 NO
方法有条件地将指令应用于 component.This 不是 supported.The 您创建的组件可以有条件地添加或删除。
已经为 angular2
创建了一个问题,因此 angular4 也应该如此。
或者你可以选择 ng-if
<button ngIf="!condition"></button>
<button ngIf="condition" md-raised-button></button>
正如其他人所说,directives
无法动态应用。
但是,如果您只想将 md-button
的样式从 flat 切换为 raised,那么这个
<button md-button [class.mat-raised-button]="isRaised">Toggle Raised Button</button>
就可以了。 Plunker
我对你能做什么有了另一个想法。
您可以将要替换的 html 作为字符串存储在变量中,然后使用 [=11= 的 bypassSecurityTrustHtml
方法根据需要添加/删除指令].
我没有得到一个干净的解决方案,但至少你不需要重复代码。
这也可能是一个解决方案:
[md-raised-button]="condition ? 'true' : ''"
它适用于 angular 4,离子 3,如下所示:
[color]="condition ? 'primary' : ''"
其中 condition
是一个决定这是否是活动页面的函数。整个代码如下所示:
<button *ngFor="let page of ..." [color]="isActivePage(page) ? 'primary' : ''">{{ page.title }}</button>
如果你只需要添加一个属性来触发CSS规则,你可以使用下面的方法:(这不会动态地create/destroy一个指令)
<button [attr.md-raised-button]="condition ? '' : null"></button>
对你的 plunker 应用相同的方法:fork
更新:
condition ? '' : null
如何作为值:
当它是空字符串(''
)时它变成attr.md-raised-button=""
,当它的null
属性将不存在。
更新: plunker更新:fork(版本问题已修复,请注意问题最初是基于angular 4)
是的,这是可能的。
html 带有 appActiveAhover 指令的页面 :)
<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');
}
}
}
如前所述,这似乎是不可能的。至少可以用来防止某些重复的一件事是 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
.
这可能来晚了,但它是一种有条件地应用指令的可行且优雅的方法。
在指令 class 中创建输入变量:
@Input('myDirective') options: any;
应用指令时,设置输入变量的应用属性:
<div [myDirective] = {apply: someCondition}></div>
在指令方法中检查变量 this.options.apply 并根据条件应用指令逻辑:
ngAfterViewInit(): void {
if (!this.options.apply) {
return;
}
// directive logic
}
我找不到一个很好的现有解决方案,所以我构建了自己的指令来执行此操作。
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>
截至 2019 年 1 月 18 日,
这就是我在 Angular 5 及更高版本中有条件地添加指令的方式。我需要根据 darkMode
更改 <app-nav>
组件的颜色。页面是否处于深色模式。
这对我有用:
<app-nav [color]="darkMode ? 'orange':'green'"></app-nav>
我希望这对某人有所帮助。
编辑
这会根据条件更改属性(颜色)的值。碰巧颜色是使用指令定义的。所以任何阅读本文的人请不要感到困惑,这不是有条件地应用指令(即,这意味着根据条件向 dom 添加或删除指令)
也许它会对某人有所帮助。
在下面的示例中,我有 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>
代码。
将 null
传递给指令将其删除!
<button md-raised-button="condition ? true : null"></button>
我正在使用 Angular Material
,在 *ngIf
上添加一个元素对我来说效果不佳(该元素会在许多新生成的 material HTML 中消失标签哈哈)。
我不知道这是否是一个好习惯,但我使用了 OnChanges
并且我有一种条件指令 - 它起作用了! :)
我就是这样解决的:
import { Directive, Renderer2, ElementRef, Input, OnChanges, SimpleChanges, AfterViewInit } from '@angular/core';
@Directive({
selector: '[appDirtyInputIndicator]'
})
export class DirtyInputIndicatorDirective implements OnChanges, AfterViewInit {
@Input('appDirtyInputIndicator') dirtyInputIndicator: boolean;
span = this.renderer.createElement('span');
constructor(private renderer: Renderer2, private el: ElementRef) {}
ngOnChanges(changes: SimpleChanges): void {
if (changes.dirtyInputIndicator && this.dirtyInputIndicator) {
this.renderer.appendChild(this.el.nativeElement, this.span);
} else {
this.renderer.removeChild(this.el.nativeElement, this.span);
}
}
ngAfterViewInit() {
this.renderer.addClass(this.span, 'dirty_input_badge');
}
}