0

I try to modify the code that uses depreciated class DynamicComponentLoader in Angular 2.

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

}

I cannot get it to work, I try to add ComponentRef in the constructor, but it does not work:

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

I try like this:

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

It does not work.

adam nowak
  • 785
  • 2
  • 9
  • 17
  • There is an explanation with a [working plunker](http://stackoverflow.com/a/37044960/1679310) – Radim Köhler May 31 '16 at 16:42
  • What's the hack with `ViewContainerRef` for? – Günter Zöchbauer May 31 '16 at 16:43
  • Why are you using `ToastContainer` instead of `ViewContainerRef` for `target`? Can you please elaborate a bit more on "but it does not work"? – Günter Zöchbauer May 31 '16 at 17:00
  • You are right, ViewContainerRef should be used. The problem is that all the examples are on Components where the template is in the component and ViewChild also there. I have a service where I want to use it. – adam nowak May 31 '16 at 17:25
  • You understand? I have @ViewChild defined in the service, where I have not template. I have the template in a component defined which is another class. – adam nowak May 31 '16 at 17:32

1 Answers1

0

An example from 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();
    }    
  }
}

See also https://stackoverflow.com/a/37201171/217408 for how to get ViewContainerRef

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567