Угловая директива для управления видимостью / разрешением при заданной конфигурации - PullRequest
0 голосов
/ 29 мая 2019

У меня есть следующая директива, которая обрабатывает видимость / включение всех дочерних элементов, начиная с элемента, к которому она применяется.

В ngAfterViewInit директива извлекает конфигурацию элементов, предоставляющих веб-API атрибут componentName и зарегистрированную роль пользователя.После этого конфигурация применяется ко всем элементам, которые соответствуют строке в конфигурации.

import {
  Directive, Input,
  ElementRef, AfterViewInit, ViewContainerRef, Renderer2, DoCheck
} from '@angular/core';
import { CompConfig } from '../model/comp-config';
import { ConfigService } from '../services/config.service';

@Directive({
  selector: '[limsApplyConfig]'
})
export class ApplyConfigDirective implements AfterViewInit, DoCheck {


  config: CompConfig[];
  compName: string;
  constructor(
    private hostElement: ElementRef,
    private cs: ConfigService,
    private renderer: Renderer2
  ) { }

  @Input() set limsApplyConfig(compName: string) {
    this.compName = compName;
  }

  ngAfterViewInit(): void {
    // start with everything hidden: when a config will be received 
    // elements can be enabled following configuration
    this.renderer.addClass(this.hostElement.nativeElement, 'cfg-hidden');

    this.cs.getConfig(this.compName).subscribe(c => {
      this.renderer.removeClass(this.hostElement.nativeElement, 'cfg-hidden');
      this.config = c;
      this.config.forEach(cfg => {
        if (this.hostElement.nativeElement.querySelectorAll) {
          const inputCollection = this.hostElement.nativeElement.querySelectorAll('#' + cfg.ControlName);
          inputCollection.forEach(n => {
            // readonly is a property of inputs
            if (n.readOnly !== undefined) {
              n.readOnly = cfg.Disable;
            }
            // disabled is a property of buttons
            if (n.disabled !== undefined) {
              n.disabled = cfg.Disable;
            }
            if (cfg.Invisible) {
              this.renderer.addClass(n, 'cfg-hidden');
            }
          });
        }
      });
    });
  }

  ngDoCheck(): void {
    if (this.config && this.config.length > 0) {
      this.config.forEach(cfg => {
        if (this.hostElement.nativeElement.querySelectorAll) {
          const inputCollection = this.hostElement.nativeElement.querySelectorAll('#' + cfg.ControlName);
          inputCollection.forEach(n => {
            if (n.readOnly !== undefined) {
              n.readOnly = cfg.Disable;
            }
            if (n.disabled !== undefined) {
              n.disabled = cfg.Disable;
            }
            if (cfg.Invisible) {
              this.renderer.addClass(n, 'cfg-hidden');
            }
          });
        }
      });
    }
  }
}

Что касается состояния включения / выключения элементов, у меня возникают трудности с тем, чтобы директива победила конкретнуюлогика компонента.Конфигурация никогда не меняется, но состояние кнопок / входов меняется.

Другими словами, если кнопка должна быть отключена, я хочу отключить ее и оставить ее отключенной , даже если логикакомпонент включит его.К сожалению, я не могу это сделать.Я попытался добавить ngDoCheck крюк жизненного цикла, но безуспешно.

Любая помощь будет оценена

1 Ответ

0 голосов
/ 30 мая 2019

Директивы оцениваются только один раз, пока не изменится вход. Если ваш компонент меняет входные данные на директиву [и ваш компонент активирует кнопку, но вы все еще хотите отключить ее с помощью директивы, то убедитесь, что ваша подписка выполняется каждый раз, когда изменяется вход в директиву. Если мое понимание вашей проблемы верное, давайте изменим код следующим образом [импортируйте необходимые классы и простите за форматирование] -

    import {
  Directive, Input,
  ElementRef, AfterViewInit, ViewContainerRef, Renderer2, DoCheck
} from '@angular/core';
import { CompConfig } from '../model/comp-config';
import { ConfigService } from '../services/config.service';

@Directive({
  selector: '[limsApplyConfig]'
})
export class ApplyConfigDirective implements AfterViewInit, DoCheck {


  config: CompConfig[];
  compName: string;
  compName$: BehaviorSubject<string>;
  constructor(
    private hostElement: ElementRef,
    private cs: ConfigService,
    private renderer: Renderer2
  ) { 
   this.compName$ = new BehaviorSubject<string>(null);
 }

  @Input() set limsApplyConfig(compName: string) {
    this.compName$.next(compName);
  }

  ngAfterViewInit(): void {

    // start with everything hidden: when a config will be received 
    // elements can be enabled following configuration
    this.renderer.addClass(this.hostElement.nativeElement, 'cfg-hidden');

    this.compName$
        .pipe(
          mergeMap(cn => this.cs.getConfig(cn)),
          tap(config => {
            this.config.forEach(cfg => {
            if (this.hostElement.nativeElement.querySelectorAll) {
            const inputCollection = this.hostElement.nativeElement.querySelectorAll('#' 
            + cfg.ControlName);
          inputCollection.forEach(n => {
            // readonly is a property of inputs
            if (n.readOnly !== undefined) {
              n.readOnly = cfg.Disable;
            }
            // disabled is a property of buttons
            if (n.disabled !== undefined) {
              n.disabled = cfg.Disable;
            }
            if (cfg.Invisible) {
              this.renderer.addClass(n, 'cfg-hidden');
            }
          });
        }
      });
          })
        ).subscribe();

  }      
}
...