I want to create a popover
component which will have api like below:
<button popover [content]="popover_content" >popover test</button><ng-template #popover_content><ul><li>1</li><li>2</li><li>3</li><li>4</li></ul></ng-template>
I have tried to some extent, pls see stackblitz
The problem is:
- Content is appearing inside the button. How do I avoid it?
- I want the content to give it some css class but when I access it I just get a comment node.
@Input() set content(val: TemplateRef<void>) {this.popoverContent = val;console.log(val.elementRef.nativeElement);//this is a comment node. WHY??}
I am not sure how to solve above two problems. Would be great if someone could advice.
Best Answer
Since ng-template
is being compiled to comment, you can't actually get its content. You could try to set it to a hidden div and that might work (https://stackblitz.com/edit/angular-bj2ke4).
In any case, I made a small change with the API so it'll match the following pattern (I hope that's ok with you):
<app-popover buttonText="Click Me"><ul><li>THIS</li><li>IS</li><li>MY POPOVER</li></ul></app-popover>
It's pretty straight forward, popover.component.ts
:
import { Component, Input } from '@angular/core';@Component({selector: 'app-popover',templateUrl: './popover.component.html',styleUrls: ['./popover.component.css']})export class PopoverComponent {@Input() buttonText: string;isActive = false;toggle() {this.isActive = !this.isActive;}}
popover.component.html
:
<button (click)="toggle()">{{ buttonText }}</button><div class="popover" [class.active]="isActive"><ng-content></ng-content></div>
Stackblitz Demo - https://stackblitz.com/edit/angular-ovecbp
If you use ionic, you can use their ion-popover component. Otherwise, you can try a pure CSS route.
To get a basic popover working, you need a background layer with position: absolute
as well as a top z-index
. You can use height: 100%
and width: 100%
for convenience. It'll cover the entire screen.
<section class="popover-background">...</section>
Then you need to create the visible container for the popover, such as a modal over the popover-background
. You can position this container however you like, it'll be the visible popover element. This container will be relative to the absolute positioned popover-background
.
<section class="popover-background"><article class="popover-container"><!-- popover content --></article></section>
Now, you can put whatever content you need inside the container.
<section class="popover-background"><article class="popover-container"><ng-content></ng-content></article></section>
Assuming this popover belong to a my-popover
component. You can choose show the content of the popover like this:
<button (click)="showPopver()">Show Popover</button><my-popover *ngIf="show"><ul><li>1</li><li>2</li><li>3</li><li>4</li></ul></my-popover>
Additionally, you can modify this piece of code further to have dynamic popover content.
<my-popover *ngIf="show"><a *ngIf="showA"></a><b *ngIf="showB"></b></my-popover>
You can take a look at this changes that i did in the Stackblitz .
Added a mouseOver event but can also be done onClick
<div ngClass="myclass" (mouseenter)="changeStyle($event)" (mouseleave)="changeStyle($event)"><ng-content></ng-content><div *ngIf = "test"><ng-container *ngTemplateOutlet="popoverContent"></ng-container></div> </div>