如何将DynamicComponentLoader更改为新的ComponentResolver

时间:2016-05-31 16:36:37

标签: typescript angular components

我尝试修改在Angular 2中使用折旧类DynamicComponentLoader的代码。

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

  constructor(private loader: DynamicComponentLoader,
          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);

  let bindings = ReflectiveInjector.resolve([
    provide(ToastOptions, { useValue: <ToastOptions>this.options })
  ]);

  this.loader.loadNextToLocation(ToastContainer, appElement, bindings)
    .then((ref) => {
      this.container = ref;
      this.setupToast(toast);
    });
} else {
  this.setupToast(toast);
}

}

我无法让它工作,我尝试在构造函数中添加ComponentRef,但它不起作用:

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

我试着这样:

@Injectable()
export class ToastsManager {
@ViewChild('target', {read: ToastContainer}) target;
container: ComponentRef;
private options = {
autoDismiss: true,
toastLife: 3000
};
private index = 0;

constructor(private loader: DynamicComponentLoader, private resolver:     ComponentResolver, private viewContainerRef
          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);

  let bindings = ReflectiveInjector.resolve([
    provide(ToastOptions, { useValue: <ToastOptions>this.options })
  ]);

  let self = this;
  this.resolver.resolveComponent(this.type)
    .then((factory: ComponentFactory<any>) => {
        self.container = this.target.createComponent(factory);
      this.setupToast(toast);
    });
} else {
  this.setupToast(toast);
}
}

它不起作用。

1 个答案:

答案 0 :(得分:0)

来自https://stackoverflow.com/a/36325468/217408

的示例
@Component({
  selector: 'dcl-wrapper',
  template: `<div #target></div>`
})
export class DclWrapper {
  @ViewChild('target', {read: ViewContainerRef}) target;
  @Input() type;
  cmpRef:ComponentRef;
  private isViewInitialized:boolean = false;

  constructor(private resolver: ComponentResolver) {}

  updateComponent() {
    if(!this.isViewInitialized) {
      return;
    }
    if(this.cmpRef) {
      this.cmpRef.destroy();
    }
   this.resolver.resolveComponent(this.type).then((factory:ComponentFactory<any>) => {
      this.cmpRef = this.target.createComponent(factory)
    });
  }

  ngOnChanges() {
    this.updateComponent();
  }

  ngAfterViewInit() {
    this.isViewInitialized = true;
    this.updateComponent();  
  }

  ngOnDestroy() {
    if(this.cmpRef) {
      this.cmpRef.destroy();
    }    
  }
}

另请参阅https://stackoverflow.com/a/37201171/217408了解如何获取ViewContainerRef