从指令中设置 ngIf 的 Angular 指令

问题描述

我有一个自定义指令,可以动态设置输入的内容,例如占位符、必需、提示和工具提示。我还想用 *ngIf 有条件地设置它,但我不确定如何动态地做到这一点。我们正在使用 flex 并且有一个响应式表单,所以如果我们做其他技巧来隐藏字段,那么只要它不影响布局,我就很酷。所以基本上如果我们将可见性设置为 false,组件将不会显示

这是 stackblitz 的链接 - https://stackblitz.com/edit/angular-uffqz6?file=src/app/config-from.directive.ts

我知道已经有一个 angularjs 问题 - Angular directive that sets ngIf

这里的想法是有人在维护来自其他来源的标签、必需、可见性、帮助和工具提示。这用于具有多个订阅者的产品中,其中一些订阅者不以相同的方式使用该应用程序,因此使其动态化很好。我讨厌“显示字段描述”功能,但它被推送了 - 我知道这很奇怪。我试图将其剥离以了解示例的内容......非常感谢帮助,也许这里有一些东西可以帮助其他人创建纸牌屋..

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

解决方法

我现在要做的一件事就是将 display 设置为 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';
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...