2

I'm using something similar to this https://github.com/angular/angular/pull/11235 to render dynamic modals.

The directive has an input that takes the type a the Component that it will render:

    @Directive({ selector: '[ngComponentOutlet]' })
export class NgComponentOutlet implements OnChanges {
    @Input() ngComponentOutlet: Type<any>;
    @Input() ngOutletInjector: Injector;
    @Input() ngOutletProviders: Provider[];
    @Input() ngOutletProjectableNodes: any[][];

    @Output()
    ngOutletCreated = new EventEmitter<ComponentRef<any>>(false);

    constructor(
        private _cmpFactoryResolver: ComponentFactoryResolver,
        private _viewContainerRef: ViewContainerRef) { }

    ngOnChanges(changes: SimpleChanges) {
        if (changes.hasOwnProperty('ngComponentOutlet')) {
            this._viewContainerRef.clear();

            if (this.ngComponentOutlet) {
                let injector = this.ngOutletInjector || this._viewContainerRef.parentInjector;

                if (Array.isArray(this.ngOutletProviders) && this.ngOutletProviders.length > 0) {
                    injector = ReflectiveInjector.resolveAndCreate(this.ngOutletProviders, injector);
                }

                const cmpRef = this._viewContainerRef.createComponent(
                    this._cmpFactoryResolver.resolveComponentFactory(this.ngComponentOutlet),
                    this._viewContainerRef.length, injector, this.ngOutletProjectableNodes);

                this.ngOutletCreated.emit(cmpRef);
            }
        }
    }
}

I would like to enforce an interface on the components that can be used like this, so that I know that all Components dynamically rendered has a certain function, for example:

export interface ModalContent {
    close(): void;
}

All the components that are going to be dynamic modals implements this:

@Component({
    ...
})
export class MyCustomModalComponent implements ModalContent {
    close() {
        ...
    }
}

And then I put it all together

@Component({
    template: `<div [ngComponentOutlet]="component"></div>`,
})
export class AppComponent {
    private component: ModalContent;

    showModal() {
        this.component = MyCustomModalComponent; <-- I get the error here
    }
}

My problem is that I get the following error in AppComponent:

Type 'typeof MyCustomModalComponent' is not assignable to type 'ModalContent'.
Property 'close' is missing in type 'typeof MyCustomModalComponent'.

I guess it has to do with how I handle the types along the way, but I'm now sure what the problem is?

EDIT I added the entire Directive for reference

1 Answer 1

2

This code says component is of type ModalContent which means it can hold an instance of ModalContent.

private component: ModalContent;

This code assigns an instance of type Type, not of type ModalContent

this.component = MyCustomModalComponent;

This code would comply to the type annotations

this.component = new MyCustomModalComponent();

but you are not supposed to instantiate components yourself but instead let Angulars DI do it for you.

Not sure what you actually try to accomplish though.

update

If you actually want to assign a reference to the type, this should work:

private component: Type<ModalContent>
Sign up to request clarification or add additional context in comments.

4 Comments

I added the entire Directive as a reference. I want to use that in order to be able to dynamically populate a modal with different components. That part of the code works fine. I just don't know how to declare private component: ModalContent correctly. If i set private component: any, it works just fine
private component: Type; or private component: Type<ModalContent>; (not sure about the later)
You are absolutely correct about private component: Type<ModalContent>. Seems very obvious now that I see it :D Thank you! Update your answer and I'll approve it! :)
Great! Done. . . .

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.