3

What is better? Use ngFor or ViewContainerRef to dynamically create components? What is the difference?

For example, if I have a button to create a new element that every time I press it generates a new component.

1) The first option would be the following

items: number[] = [];

addItem() {
  this.items.push(1);
}

<my-component *ngFor="let item of items"></my-component>

2) The second option

@ViewChild('viewContainerRef', { read: ViewContainerRef }) VCR: ViewContainerRef;

  index: number = 0;

  componentsReferences = [];

  constructor(private CFR: ComponentFactoryResolver) {
  }

  createComponent() {

    let componentFactory = this.CFR.resolveComponentFactory(ChildComponent);
    let componentRef: ComponentRef<ChildComponent> = this.VCR.createComponent(componentFactory);
    let currentComponent = componentRef.instance;

    currentComponent.selfRef = currentComponent;
    currentComponent.index = ++this.index;

    // prividing parent Component reference to get access to parent class methods
    currentComponent.compInteraction = this;

    // add reference for newly created component
    this.componentsReferences.push(componentRef);
  }

  remove(index: number) {

    if (this.VCR.length < 1)
      return;

    let componentRef = this.componentsReferences.filter(x => x.instance.index == index)[0];
    let component: ChildComponent = <ChildComponent>componentRef.instance;

    let vcrIndex: number = this.VCR.indexOf(componentRef)

    // removing component from container
    this.VCR.remove(vcrIndex);

    this.componentsReferences = this.componentsReferences.filter(x => x.instance.index !== index);
  }

The first option is the typical way to iterate an array and display its content through a component with an ngFor. The second option uses the ViewContainerRef instead of the ngFor. An example can be seen in the following links.

https://stackblitz.com/edit/add-or-remove-dynamic-component?file=src%2Fapp%2Fparent%2Fparent.component.ts

https://stackblitz.com/edit/angular-jukjib

Mr. Mars
  • 762
  • 1
  • 9
  • 39
  • 1
    I have no idea why you would go through all the trouble of using ViewContainerRef and generating components via a factory for this type of a use case. Adding an item to an array and having *ngFor will essentially do the exact same thing and is much more reliable and maintainable. Either way, this is question is likely to get you opinion-based answers and may get closed. – mhodges Jan 31 '20 at 16:19
  • I know that using ngFor is much more readable and easy. I'm simply looking for an explanation to know if viewContainerRef offers advantages over ngFor. – Mr. Mars Jan 31 '20 at 16:33
  • I've been asking myself the same question. Your example iterates over an array of numbers which, to be fair, isn't a great example for illustrating your point. If that's all you wanted to do, you'd certainly use ngFor, no question. For me, where the line begins to blur is when you want to render several of the same component and populate it using values. It becomes a question of whether you're better off creating the populated components directly, or making an array of objects which hold the desired parameters and then using that to populate an ngFor of the desired component. – ldobson Dec 10 '21 at 11:45

1 Answers1

1

Base on my understand:

If you want to insert new component or template, you need to tell Angular where to put this element. And that's what ViewContainerRef is. It is A DOM element (container) where you can put your newly component as a sibling to this element.

*ngFor Directive in Angular. NgFor is a built-in template directive that makes it easy to iterate over something like an array or an object and create a template for each item. ... of users means that we'll be iterating over the users iterable that should be made available in our component

In summary, if you want to insert a new component or template as a sibling, you go for ViewContainerRef, if you only one to iterate over something like an array or an object and create a template in the same component, use ngFor

I hope this help. Corrections are all welcome

Venusssss
  • 488
  • 1
  • 3
  • 11