I want to know the correct way to call the greet()
method declared in the host component from a dynamically added component
src/app/app.component.ts
JavaScript
x
62
62
1
import {
2
Component,
3
ViewChild,
4
ComponentFactoryResolver,
5
ViewContainerRef,
6
} from '@angular/core';
7
8
import { OneComponent } from './application/one/one.component';
9
import { TwoComponent } from './application/two/two.component';
10
import { ThreeComponent } from './application/three/three.component';
11
import { AdHostDirective } from './ad-host.directive';
12
13
enum Target {
14
ONE = 'one',
15
TWO = 'two',
16
THREE = 'three',
17
}
18
19
@Component({
20
selector: 'app-root',
21
templateUrl: './app.component.html',
22
styleUrls: ['./app.component.css'],
23
})
24
export class AppComponent {
25
@ViewChild(AdHostDirective, { static: true }) adHost: AdHostDirective;
26
27
constructor(private componentFactoryResolver: ComponentFactoryResolver) {}
28
29
toggle(target: string): void {
30
let componentFactory: any;
31
32
switch (target) {
33
case Target.ONE:
34
componentFactory = this.componentFactoryResolver.resolveComponentFactory(
35
OneComponent
36
);
37
break;
38
case Target.TWO:
39
componentFactory = this.componentFactoryResolver.resolveComponentFactory(
40
TwoComponent
41
);
42
break;
43
case Target.THREE:
44
componentFactory = this.componentFactoryResolver.resolveComponentFactory(
45
ThreeComponent
46
);
47
break;
48
default:
49
break;
50
}
51
52
const viewContainerRef = this.adHost.viewContainerRef;
53
54
viewContainerRef.clear();
55
viewContainerRef.createComponent(componentFactory);
56
}
57
58
greet(): void {
59
alert('Hi');
60
}
61
}
62
src/app/ad-host.directive.ts
JavaScript
1
9
1
import { Directive, ViewContainerRef } from '@angular/core';
2
3
@Directive({
4
selector: '[appAddHost]',
5
})
6
export class AdHostDirective {
7
constructor(public viewContainerRef: ViewContainerRef) {}
8
}
9
src/app/app.component.html
JavaScript
1
6
1
<button (click)="toggle('one')">One</button>
2
<button (click)="toggle('two')">Two</button>
3
<button (click)="toggle('three')">Three</button>
4
5
<ng-template appAddHost></ng-template>
6
In my case there are three components that are dynamically added in all of them I need to call a method in the host component, for example in component One
src/app/application/one/one.component.ts
JavaScript
1
17
17
1
import { Component, OnInit, Output, EventEmitter } from '@angular/core';
2
3
@Component({
4
selector: 'app-one',
5
templateUrl: './one.component.html',
6
styleUrls: ['./one.component.css'],
7
})
8
export class OneComponent implements OnInit {
9
constructor() {}
10
11
ngOnInit(): void {}
12
13
onClick(): void {
14
// how to call host component greet method?
15
}
16
}
17
src/app/application/one/one.component.html
JavaScript
1
4
1
<p>one works!</p>
2
3
<button (click)="onClick()">On click</button>
4
Update 1
I share the repository of the listed examples to facilitate your collaboration
https://github.com/ilmoralito/add-components-dynamically-demo-app
Thanks for your comments
Advertisement
Answer
You can add an output()
in OneComponent
then you subscribe in your AppComponent
like below:
JavaScript
1
22
22
1
import { Component, OnInit, Output, EventEmitter } from '@angular/core';
2
3
@Component({
4
selector: 'app-one',
5
templateUrl: './one.component.html',
6
styleUrls: ['./one.component.css'],
7
})
8
export class OneComponent implements OnInit {
9
10
@Output()
11
greetEvent: EventEmitter<void> = new EventEmitter<void>();
12
13
constructor() {}
14
15
ngOnInit(): void {}
16
17
onClick(): void {
18
// how to call host component greet method?
19
this.greetEvent.emit();
20
}
21
}
22
src/app/app.component.ts
JavaScript
1
63
63
1
import {
2
Component,
3
ViewChild,
4
ComponentFactoryResolver,
5
ViewContainerRef,
6
} from '@angular/core';
7
8
import { OneComponent } from './application/one/one.component';
9
import { TwoComponent } from './application/two/two.component';
10
import { ThreeComponent } from './application/three/three.component';
11
import { AdHostDirective } from './ad-host.directive';
12
13
enum Target {
14
ONE = 'one',
15
TWO = 'two',
16
THREE = 'three',
17
}
18
19
@Component({
20
selector: 'app-root',
21
templateUrl: './app.component.html',
22
styleUrls: ['./app.component.css'],
23
})
24
export class AppComponent {
25
@ViewChild(AdHostDirective, { static: true }) adHost: AdHostDirective;
26
27
constructor(private componentFactoryResolver: ComponentFactoryResolver) {}
28
29
toggle(target: string): void {
30
let componentFactory: any;
31
32
switch (target) {
33
case Target.ONE:
34
componentFactory = this.componentFactoryResolver.resolveComponentFactory(
35
OneComponent
36
);
37
break;
38
case Target.TWO:
39
componentFactory = this.componentFactoryResolver.resolveComponentFactory(
40
TwoComponent
41
);
42
break;
43
case Target.THREE:
44
componentFactory = this.componentFactoryResolver.resolveComponentFactory(
45
ThreeComponent
46
);
47
break;
48
default:
49
break;
50
}
51
52
const viewContainerRef = this.adHost.viewContainerRef;
53
54
viewContainerRef.clear();
55
const componentRef: ComponentRef<any> = viewContainerRef.createComponent(componentFactory);
56
componentRef.instance.greetEvent.subscribe(() => this.greet());
57
}
58
59
greet(): void {
60
alert('Hi');
61
}
62
}
63