Skip to content

Instantly share code, notes, and snippets.

@talamaska
Last active November 11, 2020 09:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save talamaska/ae5572d58d0e5cebcb32b23964ddb464 to your computer and use it in GitHub Desktop.
Save talamaska/ae5572d58d0e5cebcb32b23964ddb464 to your computer and use it in GitHub Desktop.
template modals
interface CustomOverlayConfig {
hasBackdropClick?: boolean;
isCentered?: boolean;
size?: any;
top?: string;
}
const DEFAULT_CUSTOM_CONFIG: CustomOverlayConfig = {
hasBackdropClick: false,
isCentered: true,
size: null
};
@Injectable()
export class TemplateModalService {
public dialogRef: TemplateModalOverlayRef;
public customConfig: CustomOverlayConfig;
constructor(
private injector: Injector,
private overlay: Overlay
) { }
open(templateRef: CdkPortal, config: FormModalConfig = {}, customConfig: CustomOverlayConfig = {}) {...}
public dialogRef: TemplateModalOverlayRef;
@ViewChild('ratingModal') ratingModal: TemplatePortal<any>;
public closeModal() {
this.dialogRef.close();
this.modalData.next({});
}
<ng-template cdkPortal #ratingModal="cdkPortal">
<rating-modal [modalData]="modalData | async" (close)="closeModal()" (ratings)="updateRating($event)" (rate)="rateEvent($event)"></rating-modal>
</ng-template>
this.dialogRef = this.modalService.open(this.ratingModal, {}, {
isCentered: false
});
import { OverlayRef } from '@angular/cdk/overlay';
export class TemplateModalOverlayRef {
constructor(private overlayRef: OverlayRef) { }
close(): void {
this.overlayRef.dispose();
}
}
private attachModalContainer(
overlayRef: OverlayRef,
config: FormModalConfig,
dialogRef: TemplateModalOverlayRef,
templateRef: CdkPortal // this was added
) {
const containerRef = overlayRef.attach(templateRef); // this was changed
return containerRef;
}
private getOverlayConfig(config: FormModalConfig): OverlayConfig {
let positionStrategy = this.overlay.position()
.global();
if (this.customConfig.isCentered) {
positionStrategy = positionStrategy
.centerHorizontally()
.centerVertically();
}
if (this.customConfig.size) {
positionStrategy = positionStrategy
.width(this.customConfig.size.width)
.height(this.customConfig.size.height);
}
if (this.customConfig.top) {
positionStrategy = positionStrategy
.top(this.customConfig.top)
.centerHorizontally();
}
@capaneus
Copy link

capaneus commented Jan 18, 2019

hi Zlati,
Thanks for you article introducing 3 ways to create a Modal Window. It's really brilliant. My personal preference is the 3rd solution, I'm trying to follow the article but blocked.
in template.modal.service.ts -> attachModalContainer function, the injector wasn't used, so there is no place to connect the TemplateModalOverlayRef with templateRef: CdkPortalm, in previous solution when using ComponentPortal, this link was bridged through injector
So when I tried the 3rd method, at first it failed at
#ratingModal="cdkPortal"
It complains there is no directive with "exportAs" set to "cdkPortal"
then I removed ="cdkPortal"
it complains: Attempting to attach an unknown Portal type. BasePortalOutlet accepts either a ComponentPortal or a TemplatePortal
at here: const containerRef = overlayRef.attach(templateRef);

Is there anything missing in the sample?

Thanks!

@jeremyputeaux
Copy link

Actually, in step 3 you can remove all lines related to injector.
Also you probably forgot to import PortalModule.

@sambanthar
Copy link

sambanthar commented Jul 19, 2020

  1. Remote-Controlled Template-Based Modals
    please give me complete example to understand better. kindly give me the link full project setup

@talamaska
Copy link
Author

talamaska commented Jul 20, 2020

@sambanthar

  1. Remote-Controlled Template-Based Modals
    please give me complete example to understand better. kindly give me the link full project setup

Full example, little bit outdated so you'll have to migrate some apis that changed in A9.

https://stackblitz.com/edit/angular-cdk-modals

@talamaska
Copy link
Author

talamaska commented Jul 20, 2020

@jeremyputeaux

Actually, in step 3 you can remove all lines related to injector.
Also you probably forgot to import PortalModule.

You're right I don't use the injector in the template driven modal

@talamaska
Copy link
Author

talamaska commented Jul 20, 2020

@capaneus

Also you probably forgot to import PortalModule.

the remote controlling of the template modal is performed via the ViewChild ratingModal

@rjstalb
Copy link

rjstalb commented Oct 13, 2020

I'm also getting error 'there is no directive with exportAs set to cdkPortal'. I've made all of the adjustments, and I'm importing PortalModule. Was this every resolved?

@rjstalb
Copy link

rjstalb commented Oct 13, 2020

I'm also getting error 'there is no directive with exportAs set to cdkPortal'. I've made all of the adjustments, and I'm importing PortalModule. Was this every resolved?

Gotta love it - a minute after I submit this, I found my error. I was not, in fact, importing Portal Module in the correct dependent component module.

Anyway, thanks for the great tutorial!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment