UNPKG

@progress/kendo-angular-dialog

Version:
227 lines (226 loc) 9.23 kB
/**----------------------------------------------------------------------------------------- * 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); } } /** * A service for opening Windows dynamically * ([see example]({% slug service_window %})). */ export class WindowService { resolver; containerService; constructor( /** * @hidden */ resolver, containerService) { this.resolver = resolver; this.containerService = containerService; } /** * Opens a Window component. * * @param {WindowSettings} settings - The settings that define the Window. * @returns {WindowRef} - A reference to the Window object. * * @example * * ```ts-no-run * _@Component({ * selector: 'my-app', * template: ` * <button kendoButton (click)="open()">Open window</button> * <div kendoWindowContainer></div> * ` * }) * export class AppComponent { * constructor( private windowService: WindowService ) {} * * public open() { * var window = this.windowService.open({ * title: "My window", * content: "My content!" * }); * * window.result.subscribe((result) => { * if (result instanceof WindowCloseResult) { * console.log("Window was closed"); * } * }); * } * } * ``` * */ 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] }] }]; } });