Angular 从指令中设置 ngIf 的指令
Angular directive that sets ngIf from within the directive
我有一个自定义指令,可以动态设置输入内容,例如占位符、必需、提示和工具提示。我也想有条件地用 *ngIf 设置它,但我不确定如何动态地做到这一点。我们正在使用 flex 并具有响应式表单,因此如果我们使用其他技巧来隐藏字段,那么只要它不影响布局,我就可以了。所以基本上,如果我们将可见性设置为 false,组件将不会显示。
这是 stackblitz 的 link - https://stackblitz.com/edit/angular-uffqz6?file=src/app/config-from.directive.ts
我知道已经有一个 angularjs 问题 -
这里的想法是有人维护来自其他来源的标签、必需、可见性、帮助和工具提示。这用于具有多个订阅者的产品中,其中一些订阅者不以相同的方式使用应用程序,因此最好使其动态化。我讨厌“显示字段描述”功能,但它被推送了——我知道这很奇怪。我试图将其剥离以了解示例的实质...非常感谢您的帮助,也许这里有一些东西可以帮助其他人创建纸牌屋..
import { AfterViewInit, Directive, ElementRef, Input, OnDestroy, OnInit, Renderer2, Self } from '@angular/core';
import { NgModel } from '@angular/forms';
import { MatInput } from '@angular/material/input';
import { MatTooltip } from '@angular/material/tooltip';
import { Observable, of, Subscription } from 'rxjs';
import { FieldConfigService } from './config.service';
@Directive({
selector: 'input[configFrom]'
})
export class ConfigFromDirective implements OnInit, AfterViewInit, OnDestroy {
protected _visibleHelp = false;
protected helpMessage: string;
protected hint: any;
protected inputElement: any;
protected subs: Subscription[] = [];
protected name: string;
@Input() configFrom = '';
constructor(
protected model: NgModel,
// @Optional() @Self() public ngControl: NgControl,
private configService: FieldConfigService,
protected el: ElementRef,
protected renderer: Renderer2,
@Self() protected input: MatInput,
protected matTooltip: MatTooltip
) {
if (el.nativeElement) {
this.inputElement = el.nativeElement;
}
}
ngOnInit() {
this.name = this.model.name;
console.log('Looking at', this.name);
this.subs.push(this.configService.findByObject(this.configFrom).subscribe(configuration => {
let config = configuration[this.configFrom][this.name];
this.input.placeholder = config.label;
this.input.required = config.required;
this.matTooltip.message = config.helpMessage;
this.helpMessage = config.helpMessage;
})
);
this.subs.push(this.configService.showHelp$.subscribe(showHelp => {
this._visibleHelp = showHelp;
this.checkShowMessage();
})
);
}
ngAfterViewInit(): void {
this.checkShowMessage();
}
ngOnDestroy(): void {
this.subs.forEach(sub => {
if (sub && !sub.closed) {
sub.unsubscribe();
}
});
}
protected checkShowMessage() {
let input = this.getMatFormFieldParent();
if (input) {
if (!this.hint) {
this.hint = this.renderer.createElement('mat-hint');
this.renderer.appendChild(input, this.hint);
this.renderer.addClass(this.hint, 'help-hint');
}
if (this._visibleHelp) {
this.renderer.addClass(this.hint, 'help-hint');
this.renderer.removeClass(this.hint, 'hidden');
} else {
this.renderer.addClass(this.hint, 'hidden');
this.renderer.removeClass(this.hint, 'help-hint');
}
this.hint.innerHTML = this.helpMessage;
}
}
protected getMatFormFieldParent(): any {
let input = this.inputElement;
let depth = 0;
while (depth < 5 && input) {
if (
input.parentElement &&
input.parentElement.tagName == 'MAT-FORM-FIELD'
) {
return input.parentElement;
}
input = input.parentElement;
depth++;
}
return null;
}
}
我现在正在做的一件事就是将显示设置为 none。我不确定这所有的后果,但它没有显示元素和 flex 负责移动周围的东西。与 ngIf 不同,该组件仍然存在于 DOM 中。欢迎任何反馈或更好的解决方案!
//existing code
this.matTooltip.message = config.helpMessage;
this.helpMessage = config.helpMessage;
//additional change for visibility.
if (!config.visible) {
this.getMatFormFieldParent().style.display = 'none';
}
我有一个自定义指令,可以动态设置输入内容,例如占位符、必需、提示和工具提示。我也想有条件地用 *ngIf 设置它,但我不确定如何动态地做到这一点。我们正在使用 flex 并具有响应式表单,因此如果我们使用其他技巧来隐藏字段,那么只要它不影响布局,我就可以了。所以基本上,如果我们将可见性设置为 false,组件将不会显示。
这是 stackblitz 的 link - https://stackblitz.com/edit/angular-uffqz6?file=src/app/config-from.directive.ts
我知道已经有一个 angularjs 问题 -
这里的想法是有人维护来自其他来源的标签、必需、可见性、帮助和工具提示。这用于具有多个订阅者的产品中,其中一些订阅者不以相同的方式使用应用程序,因此最好使其动态化。我讨厌“显示字段描述”功能,但它被推送了——我知道这很奇怪。我试图将其剥离以了解示例的实质...非常感谢您的帮助,也许这里有一些东西可以帮助其他人创建纸牌屋..
import { AfterViewInit, Directive, ElementRef, Input, OnDestroy, OnInit, Renderer2, Self } from '@angular/core';
import { NgModel } from '@angular/forms';
import { MatInput } from '@angular/material/input';
import { MatTooltip } from '@angular/material/tooltip';
import { Observable, of, Subscription } from 'rxjs';
import { FieldConfigService } from './config.service';
@Directive({
selector: 'input[configFrom]'
})
export class ConfigFromDirective implements OnInit, AfterViewInit, OnDestroy {
protected _visibleHelp = false;
protected helpMessage: string;
protected hint: any;
protected inputElement: any;
protected subs: Subscription[] = [];
protected name: string;
@Input() configFrom = '';
constructor(
protected model: NgModel,
// @Optional() @Self() public ngControl: NgControl,
private configService: FieldConfigService,
protected el: ElementRef,
protected renderer: Renderer2,
@Self() protected input: MatInput,
protected matTooltip: MatTooltip
) {
if (el.nativeElement) {
this.inputElement = el.nativeElement;
}
}
ngOnInit() {
this.name = this.model.name;
console.log('Looking at', this.name);
this.subs.push(this.configService.findByObject(this.configFrom).subscribe(configuration => {
let config = configuration[this.configFrom][this.name];
this.input.placeholder = config.label;
this.input.required = config.required;
this.matTooltip.message = config.helpMessage;
this.helpMessage = config.helpMessage;
})
);
this.subs.push(this.configService.showHelp$.subscribe(showHelp => {
this._visibleHelp = showHelp;
this.checkShowMessage();
})
);
}
ngAfterViewInit(): void {
this.checkShowMessage();
}
ngOnDestroy(): void {
this.subs.forEach(sub => {
if (sub && !sub.closed) {
sub.unsubscribe();
}
});
}
protected checkShowMessage() {
let input = this.getMatFormFieldParent();
if (input) {
if (!this.hint) {
this.hint = this.renderer.createElement('mat-hint');
this.renderer.appendChild(input, this.hint);
this.renderer.addClass(this.hint, 'help-hint');
}
if (this._visibleHelp) {
this.renderer.addClass(this.hint, 'help-hint');
this.renderer.removeClass(this.hint, 'hidden');
} else {
this.renderer.addClass(this.hint, 'hidden');
this.renderer.removeClass(this.hint, 'help-hint');
}
this.hint.innerHTML = this.helpMessage;
}
}
protected getMatFormFieldParent(): any {
let input = this.inputElement;
let depth = 0;
while (depth < 5 && input) {
if (
input.parentElement &&
input.parentElement.tagName == 'MAT-FORM-FIELD'
) {
return input.parentElement;
}
input = input.parentElement;
depth++;
}
return null;
}
}
我现在正在做的一件事就是将显示设置为 none。我不确定这所有的后果,但它没有显示元素和 flex 负责移动周围的东西。与 ngIf 不同,该组件仍然存在于 DOM 中。欢迎任何反馈或更好的解决方案!
//existing code
this.matTooltip.message = config.helpMessage;
this.helpMessage = config.helpMessage;
//additional change for visibility.
if (!config.visible) {
this.getMatFormFieldParent().style.display = 'none';
}