Created
April 9, 2025 10:52
-
-
Save Armenvardanyan95/f74e01d396ff39bca373c0b1b7be7f0a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Injectable({providedIn: 'root'}) | |
export class PortalService { | |
// we can have multiple portals | |
portals = signal<Record<string, TemplateRef<any>>>({}); | |
// get one of the templates to use in your component | |
getPortal(portalName: string) { | |
return computed(() => this.portals()[portalName]); | |
} | |
// add a new template | |
setPortal(portalName: string, template: TemplateRef<any>) { | |
this.portals.update(portals => ({ | |
...portals, | |
[portalName]: template | |
})); | |
} | |
} | |
@Directive({ | |
selector: '[appPortal]', | |
}) | |
export class PortalDirective implements AfterViewInit { | |
portalName = input.required<string>({alias: 'appPortal'}); | |
templateRef = inject(TemplateRef); | |
portalService = inject(PortalService); | |
ngAfterViewInit(): void { | |
// pick up the template and send it to whenever we want it projected | |
this.portalService.setPortal(this.portalName(), this.templateRef); | |
} | |
} | |
@Component({ | |
selector: 'app-header', | |
template: ` | |
<header> | |
Ng App | |
@if (headerTemplate()) { | |
// get the particular template and project it in another component | |
<ng-container *ngTemplateOutlet="headerTemplate()"/> | |
} | |
</header> | |
`, imports: [NgTemplateOutlet] | |
}) | |
export class HeaderComponent { | |
portalService = inject(PortalService); | |
headerTemplate = this.portalService.getPortal('header'); | |
} | |
// then, somewhere in some template: | |
<span *appPortal="'header'">Some Content</span> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment