eckig-kundenspezifisch-modal
@ Stephen Paul Fortsetzung ...
- Angular 2 und höher Bootstrap CSS (Animation bleibt erhalten)
- KEINE JQuery
- KEINE bootstrap.js
- Unterstützt benutzerdefinierte modale Inhalte
- Unterstützung für mehrere übereinanderliegende Modalitäten.
- Modalisiert
- Deaktivieren Sie den Bildlauf, wenn Modal geöffnet ist
- Modal wird beim Wegnavigieren zerstört.
- Lazy Content Initialisierung, die
ngOnDestroy
beim Beenden des Modals (ed) wird.
- Übergeordnetes Scrollen deaktiviert, wenn Modal sichtbar ist
Lazy Content Initialisierung
Warum?
In einigen Fällen möchten Sie möglicherweise nicht modal arbeiten, um den Status nach dem Schließen beizubehalten, sondern den ursprünglichen Zustand wiederherstellen.
Ursprüngliche modale Ausgabe
Wenn Sie den Inhalt direkt in die Ansicht übergeben, wird er tatsächlich initialisiert, noch bevor das Modal ihn erhält. Das Modal hat keine Möglichkeit, solche Inhalte zu töten, selbst wenn ein *ngIf
Wrapper verwendet wird.
Lösung
ng-template
. ng-template
wird erst gerendert, wenn Sie dazu aufgefordert werden.
my-component.module.ts
...
imports: [
...
ModalModule
]
my-component.ts
<button (click)="reuseModal.open()">Open</button>
<app-modal #reuseModal>
<ng-template #header></ng-template>
<ng-template #body>
<app-my-body-component>
<!-- This component will be created only when modal is visible and will be destroyed when it's not. -->
</app-my-body-content>
<ng-template #footer></ng-template>
</app-modal>
modal.component.ts
export class ModalComponent ... {
@ContentChild('header') header: TemplateRef<any>;
@ContentChild('body') body: TemplateRef<any>;
@ContentChild('footer') footer: TemplateRef<any>;
...
}
modal.component.html
<div ... *ngIf="visible">
...
<div class="modal-body">
ng-container *ngTemplateOutlet="body"></ng-container>
</div>
Verweise
Ich muss sagen, dass es ohne die exzellente offizielle und Community-Dokumentation im Internet nicht möglich gewesen wäre. Es könnte einige von euch helfen zu verstehen besser , wie ng-template
, *ngTemplateOutlet
und @ContentChild
Arbeit.
https://angular.io/api/common/NgTemplateOutlet
https://blog.angular-university.io/angular-ng-template-ng-container-ngtemplateoutlet/
https://medium.com/claritydesignsystem/ng-content -the-hidden-docs-96a29d70d11b
https://netbasal.com/understanding-viewchildren-contentchildren-and-querylist-in-angular-896b0c689f6e
https://netbasal.com/understanding-viewchildren-contentchildren-and-querylist-in -angular-896b0c689f6e
Vollständige Copy-Paste-Lösung
modal.component.html
<div
(click)="onContainerClicked($event)"
class="modal fade"
tabindex="-1"
[ngClass]="{'in': visibleAnimate}"
[ngStyle]="{'display': visible ? 'block' : 'none', 'opacity': visibleAnimate ? 1 : 0}"
*ngIf="visible">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<ng-container *ngTemplateOutlet="header"></ng-container>
<button class="close" data-dismiss="modal" type="button" aria-label="Close" (click)="close()">×</button>
</div>
<div class="modal-body">
<ng-container *ngTemplateOutlet="body"></ng-container>
</div>
<div class="modal-footer">
<ng-container *ngTemplateOutlet="footer"></ng-container>
</div>
</div>
</div>
</div>
modal.component.ts
/**
* @Stephen Paul https://stackoverflow.com/a/40144809/2013580
* @zurfyx https://stackoverflow.com/a/46949848/2013580
*/
import { Component, OnDestroy, ContentChild, TemplateRef } from '@angular/core';
@Component({
selector: 'app-modal',
templateUrl: 'modal.component.html',
styleUrls: ['modal.component.scss'],
})
export class ModalComponent implements OnDestroy {
@ContentChild('header') header: TemplateRef<any>;
@ContentChild('body') body: TemplateRef<any>;
@ContentChild('footer') footer: TemplateRef<any>;
public visible = false;
public visibleAnimate = false;
ngOnDestroy() {
// Prevent modal from not executing its closing actions if the user navigated away (for example,
// through a link).
this.close();
}
open(): void {
document.body.style.overflow = 'hidden';
this.visible = true;
setTimeout(() => this.visibleAnimate = true, 200);
}
close(): void {
document.body.style.overflow = 'auto';
this.visibleAnimate = false;
setTimeout(() => this.visible = false, 100);
}
onContainerClicked(event: MouseEvent): void {
if ((<HTMLElement>event.target).classList.contains('modal')) {
this.close();
}
}
}
modal.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ModalComponent } from './modal.component';
@NgModule({
imports: [
CommonModule,
],
exports: [ModalComponent],
declarations: [ModalComponent],
providers: [],
})
export class ModalModule { }