Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically load component in div - Angular5

I was able to successfully create a button that on click loads another instance of my component into the DOM, but it loads it outside the component I want it to be inside which results with the CSS being off. When I add "editorComponents" to my page it currently looks like this:

enter image description here

But I want it to look like this:

enter image description here

You can see from the inspection that in the second example all of the tags are manually moved to where I want them to be.

Right now my code is as follows:

home.component.html

<div class="row backgroundContainer">

  <div class="col-md-7 componentContainer">
    <app-editor></app-editor>
    <button (click)="addEditor()" type="button">Add Editor</button>
  </div>

  <div class="col-md-5 componentContainer">
    <app-bible></app-bible>
  </div>

  <div id="footerBox">
    <app-footer></app-footer>
  </div>
  
</div>

home.component.ts

import { Component, OnInit, ViewContainerRef, ComponentFactoryResolver } from '@angular/core';
import { EditorComponent } from '../editor/editor.component';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {

  constructor(private componentFactoryResolver: ComponentFactoryResolver,
    private viewContainerRef: ViewContainerRef) {}

  ngOnInit() {
  }

  addEditor() {
    const factory = this.componentFactoryResolver.resolveComponentFactory(EditorComponent);
    const ref = this.viewContainerRef.createComponent(factory);
    ref.changeDetectorRef.detectChanges();
  }

}

So how do I make it so when I dynamically add an EditorComponent to my page it is added directly below the current "app-editor" in my html?

like image 262
FrankTheTank Avatar asked Feb 10 '18 21:02

FrankTheTank


People also ask

How can you dynamically load the component?

To dynamically load the component, we use the directive as an anchor and create the component into its position in the DOM. The createComponent method requires the component type, not the instance.

Which of the following directives is used to add a component at runtime in angular5?

To add the component to the template, you call createComponent() on ViewContainerRef .

How do you use dynamic ViewChild?

We can use ViewChildren to get the QueryList of elements or directives from the view DOM. Any time a child element is added, removed, or moved, the query list will be updated, and the changes observable of the query list will emit a new value.


1 Answers

You need to use your own ViewContainerRef. Currently you injecting root one and as you can see all your components appended to <app-root>.

import { Component, OnInit, ViewContainerRef, ComponentFactoryResolver } from '@angular/core';
import { EditorComponent } from '../editor/editor.component';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
  // Setup custom viewChild here
  @ViewChild('container', { read: ViewContainerRef }) viewContainerRef: ViewContainerRef;    

  constructor(private componentFactoryResolver: ComponentFactoryResolver) {}

  ngOnInit() {
  }

  addEditor() {
    const factory = this.componentFactoryResolver.resolveComponentFactory(EditorComponent);
    const ref = this.viewContainerRef.createComponent(factory);
    ref.changeDetectorRef.detectChanges();
  }

}

Now inside your home.component.html put this where you want your editors to be instantiated

<div #container></div>

You can use any html tag here.

Now all your editors will be inside this block.

like image 112
Vitalii Chmovzh Avatar answered Nov 09 '22 05:11

Vitalii Chmovzh