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