How to get rid of this hack

2019-09-16 06:32发布

问题:

I want to modify the class so that it does not use the ApplicationRef. In other words how to get hold of main app not using app ref.

@Injectable()
export class ToastsManager {
  container: ComponentRef<any>;
  private options = {
    autoDismiss: true,
    toastLife: 1000
  };
  private index = 0;
  container: ComponentRef<any>;
  private options = {
    autoDismiss: true,
    toastLife: 1000
  };
  private index = 0;

  constructor(private resolver: ComponentResolver,
          private appRef: ApplicationRef,
          @Optional() @Inject(ToastOptions) options) {
    if (options) {
      Object.assign(this.options, options);
    }
  }

  show(toast: Toast) {
    if (!this.container) {
      // a hack to get app element in shadow dom
      let appElement: ViewContainerRef = new     ViewContainerRef_(this.appRef['_rootComponents'][0]._hostElement);

      this.resolver.resolveComponent(ToastContainer)
        .then((factory: ComponentFactory<any>) => {
          this.container = appElement.createComponent(factory);
          this.setupToast(toast);
      });
    } else {
      this.setupToast(toast);
    }
  }

I try with the @ViewChild but it does not work.

回答1:

You could do with ApplicationRef what Brandon Roberts demonstrates in https://github.com/angular/angular/issues/4112#issuecomment-139381970 to get a reference to the Router in CanActivate().

Probably better would be a shared service

@Injectable() 
export class Shared {
  appRef = new BehaviorSubject();

  setAppRef(appRef:ApplicationRef) {
    this.appRef.emit(appRef);
  }
}
export class ToastsManager {

  constructor(private resolver: ComponentResolver,
          private appRef: ApplicationRef,
          shared:Shared,
          @Optional() @Inject(ToastOptions) options) {
    shared.setAppRef(appRef);
  }
}
export class OtherClassThatNeedsAppRef {

  constructor(shared:Shared) {
    shared.appRef.subscribe(appRef => this.appRef = appRef);
  }
}