我可以通过@HostBinding以其他方式访问主机绑定吗?

时间:2017-09-29 22:16:25

标签: angular typescript observable

我的根本问题是我需要设置一个alters an attribute of the host的异步函数。由于@HostBinding没有异步功能,我在组件上设置了一个实例变量,绑定了该变量,并手动维护了该变量。为了让它在没有臭名昭着的ExpressionChangedAfterItHasBeenCheckedError的情况下工作,我需要这样做

@Component(...) 
export class MyComponent implements OnChanges {
  constructor(private readonly cdr: ChangeDetectorRef) {}

  @Input() inputObservable: Observable<boolean>;
  @HostBinding('class.some-class') private setCssClass: boolean;

  ngOnChanges() {
    this.inputObservable.do(v => {
      if (this.setCssClass !== v) {
        setTimeout(() => {
                    this.setCssClass = v;
                    this.cdr.detectChanges();
                  }, 0);
     }
   })
   .subscribe();
  }
}

这太糟糕了。

是否有一些更干净的方式告诉父母“这里有一个变量的新值,让你随意设置”?

修改

它甚至都不起作用。在特殊情况下,setTimeout可以在组件被正式销毁之后执行,这导致异常需要整个“其他级别的hacky可怕性来防止。”

1 个答案:

答案 0 :(得分:3)

您只需使用Renderer方法进行ElementRef即可。一旦组件被销毁,不要忘记取消订阅您的Observable:

@Component(...) 
export class MyComponent implements OnInit, OnDestroy {
  constructor(private element: ElementRef, private renderer: Renderer2) {}

  @Input() 
  public inputObservable: Observable<boolean>;

  private ngUnsubscribe = new Subject<void>()

  ngOnInit() {
    this.inputObservable
      .takeUntil(this.ngUnsubscribe)
      .do(v => this.toggleClass('some-class', v))
      .subscribe()
  }

  ngOnDestroy() {
    this.ngUnsubscribe.next();
    this.ngUnsubscribe.complete();
  }

  private toggleClass(klass: string, state: boolean) {
    if(!this.element.nativeElement) return;
    if(state) {
      this.renderer.addClass(this.element.nativeElement, klass)
    } else {
      this.renderer.removeClass(this.element.nativeElement, klass)
    }
  }
}

第二种方法是将组件的输入更改为boolean,然后从父组件输入带有async的observable - pipe:

@Input()
@HostBinding('class.some-class')
public myInput: boolean;

父组件

<my-component [myInput]="myObservable$ | async"></my-component>