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:
But I want it to look like this:
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?
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.
To add the component to the template, you call createComponent() on ViewContainerRef .
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With