@progress/kendo-angular-dialog
Version:
Dialog Package for Angular
207 lines (206 loc) • 8.7 kB
JavaScript
/**-----------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the project root for more information
*-------------------------------------------------------------------------------------------*/
import { ComponentFactoryResolver, Injectable, Renderer2, TemplateRef, Inject } from '@angular/core';
import { merge, Subject } from 'rxjs';
import { filter, map, share, take } from 'rxjs/operators';
import { WindowComponent } from './window.component';
import { isPresent, isString } from '../common/util';
import { WindowContainerService } from '../window/window-container.service';
import { WindowRef } from './models/window-ref';
import { WindowCloseResult } from './models/window-close-result';
import * as i0 from "@angular/core";
import * as i1 from "../window/window-container.service";
const isNotComponent = (component) => isString(component) || component instanceof TemplateRef;
class WindowInjector {
getWindowRef;
parentInjector;
constructor(getWindowRef, parentInjector) {
this.getWindowRef = getWindowRef;
this.parentInjector = parentInjector;
}
get(token, notFoundValue) {
if (token === WindowRef) {
return this.getWindowRef();
}
return this.parentInjector.get(token, notFoundValue);
}
}
/**
* Provides methods for opening Windows dynamically.
*
* Use this service to open a Window component and manage its lifecycle. ([See example.]({% slug service_window %}))
*/
export class WindowService {
resolver;
containerService;
constructor(
/**
* @hidden
*/
resolver, containerService) {
this.resolver = resolver;
this.containerService = containerService;
}
/**
* Opens a Window component with the specified settings.
*
* @param settings The settings that configure the Window.
* @returns A `WindowRef` instance for controlling the Window.
*
* @example
* ```ts
* const window = windowService.open({
* title: 'My window',
* content: 'My content!'
* });
* ```
*/
open(settings) {
const factory = this.resolver.resolveComponentFactory(WindowComponent);
const container = settings.appendTo || this.containerService.container;
if (!container) {
throw new Error(`Cannot attach window to the page.
Add an element that uses the kendoWindowContainer directive, or set the 'appendTo' property.
See https://www.telerik.com/kendo-angular-ui/components/dialogs/window/service/
`);
}
const windowRef = {
close: () => { },
content: null,
result: null,
window: null
};
const content = this.contentFrom(settings.content, container, windowRef);
const window = container.createComponent(factory, undefined, undefined, content.nodes);
windowRef.window = window;
this.applyOptions(window.instance, settings);
const apiClose = new Subject();
const close = (e) => {
apiClose.next(e || new WindowCloseResult());
if (content.componentRef) {
content.componentRef.destroy();
}
window.destroy();
};
const result = merge(apiClose, window.instance.close.pipe(map(e => (e ? e : new WindowCloseResult())), filter((e) => {
if (settings.preventClose) {
// add windowRef only when using component
const windowRefParameter = isNotComponent(settings.content) ? undefined : windowRef;
return !settings.preventClose(e, windowRefParameter);
}
return true;
}))).pipe(take(1),
// Takes care for multiple subscriptions:
// We subscribe internally and the user may subscribe to get a close result - window.result.subscribe().
// This causes multiple subscriptions to the same source and thus multiple emissions. share() solves that.
share());
result.subscribe(close);
windowRef.close = close;
windowRef.result = result;
window.changeDetectorRef.markForCheck();
return windowRef;
}
applyOptions(instance, options) {
if (isPresent(options.htmlAttributes)) {
instance.htmlAttributes = options.htmlAttributes;
}
if (isPresent(options.cssClass)) {
instance.cssClass = options.cssClass;
}
if (isPresent(options.title)) {
instance.title = options.title;
}
if (isPresent(options.keepContent)) {
instance.keepContent = options.keepContent;
}
if (isPresent(options.width)) {
instance.width = options.width;
}
if (isPresent(options.minWidth)) {
instance.minWidth = options.minWidth;
}
if (isPresent(options.height)) {
instance.height = options.height;
}
if (isPresent(options.minHeight)) {
instance.minHeight = options.minHeight;
}
if (isPresent(options.left)) {
instance.left = options.left;
}
if (isPresent(options.top)) {
instance.top = options.top;
}
if (isPresent(options.draggable)) {
instance.draggable = options.draggable;
}
if (isPresent(options.resizable)) {
instance.resizable = options.resizable;
}
if (isPresent(options.messages && options.messages.closeTitle)) {
instance.messages.closeTitle = options.messages.closeTitle;
}
if (isPresent(options.messages && options.messages.restoreTitle)) {
instance.messages.restoreTitle = options.messages.restoreTitle;
}
if (isPresent(options.messages && options.messages.maximizeTitle)) {
instance.messages.maximizeTitle = options.messages.maximizeTitle;
}
if (isPresent(options.messages && options.messages.minimizeTitle)) {
instance.messages.minimizeTitle = options.messages.minimizeTitle;
}
if (isPresent(options.autoFocusedElement)) {
instance.autoFocusedElement = options.autoFocusedElement;
}
if (isPresent(options.state)) {
instance.state = options.state;
if (options.state === 'minimized') {
instance.keepContent = true;
}
}
if (isPresent(options.themeColor)) {
instance.themeColor = options.themeColor;
}
if (options.content instanceof TemplateRef) {
instance.contentTemplate = options.content;
}
if (options.titleBarContent instanceof TemplateRef) {
instance.titleBarTemplate = options.titleBarContent;
}
}
contentFrom(content, container, windowRef) {
const renderer = container.injector.get(Renderer2);
let nodes = [];
let componentRef = null;
if (typeof content === 'string') {
nodes = [renderer.createText(content)];
}
else if (content && !(content instanceof TemplateRef)) {
const injector = new WindowInjector(() => windowRef, container.injector);
const factory = this.resolver.resolveComponentFactory(content);
componentRef = container.createComponent(factory, undefined, injector);
nodes = [componentRef.location.nativeElement];
windowRef.content = componentRef;
}
return {
componentRef,
nodes: [
[],
nodes // Content
]
};
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: WindowService, deps: [{ token: i0.ComponentFactoryResolver }, { token: WindowContainerService }], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: WindowService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: WindowService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: function () { return [{ type: i0.ComponentFactoryResolver }, { type: i1.WindowContainerService, decorators: [{
type: Inject,
args: [WindowContainerService]
}] }]; } });