0

I'm trying to create components dynamically using the ComponentFactoryResolver.

I have a component that has an @input that holds the component ref and the component inputs.

the problem is when the components are created in the DOM they hold the exact instance data.

is it possible to create the components without them holding the instance state by reference?

class TrimItemsToPopupListComponent implements OnInit, OnDestroy, AfterViewInit {
    @Input() component?: {
        ref: ComponentType<unknown>,
        inputs: Record<string, unknown>[]
    };
    constructor(
        private resolver: ComponentFactoryResolver,
        private cd: ChangeDetectorRef
    ) {}
        ngAfterViewInit(): void {
        this.componentVC.clear();
        this.inputItems.slice(0, this.trimCount).forEach(() => {
            const factory = this.resolver.resolveComponentFactory(this.component.ref);
            const componentRef = this.componentVC.createComponent(factory);

            this.component.inputs.forEach((cmpInput, index) => {
                const inputKey = Object.keys(cmpInput)[0] as string;

                // @ts-ignore
                componentRef.instance[inputKey] = this.component.inputs[index][inputKey];
            });
        });
        this.cd.detectChanges();
    }

1 Answer 1

0

You could try this:

class TrimItemsToPopupListComponent implements OnInit, OnDestroy, AfterViewInit {
    @Input() component ?: {
    ref: ComponentType<unknown>,
        inputs: Record<string, unknown>[]
    };
constructor(
        private resolver: ComponentFactoryResolver,
        private cd: ChangeDetectorRef
    ) { }
ngAfterViewInit(): void
{
    this.componentVC.clear();
    this.inputItems.slice(0, this.trimCount).forEach(() => {
        const factory = this.resolver.resolveComponentFactory(this.component.ref);

        this.component.inputs.forEach((cmpInput, index) => {
            const inputKey = Object.keys(cmpInput)[0] as string;
            const inputValue = this.component.inputs[index][inputKey];
            const inputBinding = { [inputKey]: inputValue };

        // Pass the input binding as the `inputs` property
        const componentRef = this.componentVC.createComponent(factory, undefined, undefined, [inputBinding]);
        });
    });
    this.cd.detectChanges();
}

Brief explanation:

  • The ComponentFactoryResolver is used to resolve a ComponentFactory for the component specified in the component.ref input property.
  • The inputItems array is sliced to a smaller size using the trimCount property, and a loop is performed for each item in the sliced array.
  • Within the loop, the inputs property of the component input is iterated over, and an input binding is created for each input using the inputKey and inputValue variables.
  • The createComponent() method of the ViewContainerRef is then called, passing the ComponentFactory, as well as the input binding created in the previous step, using the inputs property.

This should create multiple instances of the component, each with its own set of input bindings, rather than sharing the same instance data by reference.

Sign up to request clarification or add additional context in comments.

Comments

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.