16

I am using the following code for creating the dynamic components

import {
  Component, OnInit, ViewContainerRef, ViewChild, ViewChildren,
  ReflectiveInjector, ComponentFactoryResolver, ViewEncapsulation, QueryList, Input, AfterViewInit
} from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { forEach } from '@angular/router/src/utils/collection';
import { IComponent } from 'app/app.icomponent';


@Component({
  encapsulation: ViewEncapsulation.None,
  selector: 'dynamic-component',
  entryComponents: [HomeComponent, HighlevelSignalComponent],
  template: `
    <div #dynamicDiv [ngClass]="classFromMenu" >
     <ng-template #dynamicComponentContainer></ng-template>
    </div>
  `,
  styleUrls: [
    './dynamic-content.component.css'
  ],
})

export class DynamicComponent implements IComponent, OnInit, AfterViewInit {
  classFromMenu: any;
 @ViewChild('dynamicComponentContainer', { read: ViewContainerRef }) dynamicComponentContainer: ViewContainerRef;


  constructor(private resolver: ComponentFactoryResolver, private route: Router,
    private activatedRoute: ActivatedRoute, ) {

  }

  .......

  buildComponent(passedData) {
   // orderAndObjs has the data for creating the component

      this.orderAndObjs.forEach(obj => {
        var componentFactory = this.resolver.resolveComponentFactory(obj.component);
        var compRef = this.dynamicComponentContainer.createComponent(componentFactory);


     // compRef is the component that is created.
//Assuming the component that i am trying to create is <dynamic-component>. 


  //I want to add either a class or any other attribute like this
//<dynamic-component class="flex">
      });

    }
  }

}

The dynamic-component is created perfectly fine and everything is working as expected. But the only issue is I want to add a class for dynamic-component so that it can be

<dynamic-component class="dynamicClass">

Any help is appreciated :(

3 Answers 3

17

Hmm.. I usually add it to the selector of component that is supposed to be an entryComponent ...

selector: 'dynamic-component.someclass',
                            ^^^^^^^^^^^

to add attribute use attribute selector:

selector: 'dynamic-component[myattr=value]',

I call it hidden feature of entryComponents

but its declarative approach and can't be changed at runtime(indeed we can change it)

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

7 Comments

Good one. Didn't know that.
@yurzui .. Can you explain how it can be changed in runtime or while creating components dynamically.
While creating component dynamically you can get ComponentRef that has location property. const compRef = this.vcRef.createComponent(factory); compRef.location.nativeElement Now you have access to element and can use whatever you want to change class or attribute. In angular we usually use Renderer See answer from estus
@Shrikey It should be defined on the component that is supposed to be dynamic if you want it to have some class like flex all the time. If this isn't your intention, this option won't work for you.
@yurzui,estus .. Thanks for your answers. I used selector attribute and also Renderer to achieve what i need. :)
|
9

In Angular 5/6, using Renderer2 from @angular/core, you can do something like below:

constructor(private resolver: ComponentFactoryResolver, private route: Router,
    private activatedRoute: ActivatedRoute, private renderer2: Renderer2) {

  }

buildComponent(passedData) {
  this.orderAndObjs.forEach(obj => {
    var componentFactory = this.resolver.resolveComponentFactory(obj.component);
    var compRef = this.dynamicComponentContainer.createComponent(componentFactory);
    this.renderer2.addClass(compRef.location.nativeElement, 'flex');
  });
}

1 Comment

Agreed. In Angular 13 you can bypass the resolver and create your component with createComponent only. You can also add the class directly on the nativeElement without using Renderer2 wrapper, for example : compRef.location.nativeElement.className = 'flex';
7

High-level DOM operations are performed with Renderer2 provider. Considering that it was injected, it is:

this.renderer2.addClass(compRef.location.nativeElement, 'dynamicClass');

It should be noticed that depending on how dynamic element is attached to DOM, this may be unnecessary complication.

Considering that dynamicComponentContainer is real DOM element and not <ng-template>, the view of dynamic component can be directly mounted to the container, thus eliminating <dynamic-component> wrapper element:

Given the container:

<div class="dynamicClass" #dynamicComponentContainer></div>

It will be:

var compRef = componentFactory.create(
  this.injector,
  [],
  this.dynamicComponentContainer.element.nativeElement
);

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.