Mein Kollege Roman hat kürzlich die Veröffentlichung unserer neuen Komponentenbibliothek für Angular Taiga UI angekündigt . Die Anweisungen für die ersten Schritte besagen, dass die Anwendung in a eingeschlossen werden muss tui-root
. Lassen Sie uns herausfinden, was es tut, herausfinden, wie und warum wir Portale verwenden und was sie im Allgemeinen sind.
Was ist ein Portal?
Stellen Sie sich eine Komponente vor select
. Es gibt eine Dropdown-Liste mit Optionen zur Auswahl. Wenn Sie es an derselben Stelle im DOM wie die Komponente selbst speichern, können eine Reihe von Problemen auftreten. Nachgeschaltete Elemente können oben herausspringen und der Container kann den Inhalt abschneiden:
z-index
, Z . 100, 10000, 10001. , overflow: hidden
. ?
. z-index
. «». Root- Taiga UI . :
<tui-scroll-controls></tui-scroll-controls>
<tui-portal-host>
<div class="content"><ng-content></ng-content></div>
<tui-dialog-host></tui-dialog-host>
<ng-content select="tuiOverDialogs"></ng-content>
<tui-notifications-host></tui-notifications-host>
<ng-content select="tuiOverNotifications"></ng-content>
</tui-portal-host>
<ng-content select="tuiOverPortals"></ng-content>
<tui-hints-host></tui-hints-host>
<ng-content select="tuiOverHints"></ng-content>
tui-dialog-host
, tui-portal-host
— . -. . Taiga UI . . :
@Injectable({
providedIn: 'root',
})
export class TuiPortalService {
private host: TuiPortalHostComponent;
add<C>(componentFactory: ComponentFactory<C>, injector: Injector): ComponentRef<C> {
return this.host.addComponentChild(componentFactory, injector);
}
remove<C>({hostView}: ComponentRef<C>) {
hostView.destroy();
}
addTemplate<C>(templateRef: TemplateRef<C>, context?: C): EmbeddedViewRef<C> {
return this.host.addTemplateChild(templateRef, context);
}
removeTemplate<C>(viewRef: EmbeddedViewRef<C>) {
viewRef.destroy();
}
}
. , , — . , , .
, - . , «», .
, . :
. Material .
, . .
.
. , . , requestAnimationFrame
. — , . . , . , . , . .
:
— . Obscured. .
, . , .
:
<section
*ngFor="let item of dialogs$ | async"
polymorpheus-outlet
tuiFocusTrap
tuiOverscroll="all"
class="dialog"
role="dialog"
aria-modal="true"
[attr.aria-labelledby]="item.id"
[content]="item.component"
[context]="item"
[@tuiParentAnimation]
></section>
<div class="overlay"></div>
, ngFor
, . , . , . , .
, . Taiga UI — . - iOS Android. . , .
Observable
. , — . . . , , DI- POLYMORPHEUS_CONTEXT
. content
observer
. complete
, , next
. , , . :
const DIALOG = new PolymorpheusComponent(MyDialogComponent);
const DEFAULT_OPTIONS: MyDialogOptions = {
label: '',
size: 's',
};
@Injectable({
providedIn: 'root',
})
export class MyDialogService extends AbstractTuiDialogService<MyDialogOptions> {
protected readonly component = DIALOG;
protected readonly defaultOptions = DEFAULT_OPTIONS;
}
.
, Taiga UI, ng-polymorpheus . , , , .
tuiFocusTrap
. , DOM, , . - — :
@HostListener('window:focusin.silent', ['$event.target'])
onFocusIn(node: Node) {
if (containsOrAfter(this.elementRef.nativeElement, node)) {
return;
}
const focusable = getClosestKeyboardFocusable(
this.elementRef.nativeElement,
false,
this.elementRef.nativeElement,
);
if (focusable) {
focusable.focus();
}
}
root-. root , tuiOverscroll
. CSS- overscroll-behavior. . , , . , , .
: tui-root?
, . , root-. tui-scroll-controls
. , . <ng-content select="tuiOverDialogs"></ng-content>
. Taiga UI. , .
root event manager plugin` DI. — . , TuiRootModule
BrowserModule
, . : — .
, root-. Taiga UI open-source, «» npm. StackBlitz-. , , !