Browse Source

Introduce Dynamic MatDialog service to display dialogs over specified components.

pull/14586/head
Igor Kulikov 6 months ago
parent
commit
99501ec9be
  1. 47
      ui-ngx/src/app/shared/components/dialog/dynamic/dynamic-dialog.module.ts
  2. 85
      ui-ngx/src/app/shared/components/dialog/dynamic/dynamic-dialog.ts
  3. 27
      ui-ngx/src/app/shared/components/dialog/dynamic/dynamic-overlay-container.ts
  4. 62
      ui-ngx/src/app/shared/components/dialog/dynamic/dynamic-overlay.ts
  5. 7
      ui-ngx/src/app/shared/shared.module.ts

47
ui-ngx/src/app/shared/components/dialog/dynamic/dynamic-dialog.module.ts

@ -0,0 +1,47 @@
///
/// Copyright © 2016-2025 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { OverlayModule } from '@angular/cdk/overlay';
import { NgModule } from '@angular/core';
import { DEFAULT_DIALOG_CONFIG, DialogConfig, DialogModule } from '@angular/cdk/dialog';
import { MatDialogModule } from '@angular/material/dialog';
import { DynamicDialog, DynamicMatDialog } from './dynamic-dialog';
import { DynamicOverlay } from './dynamic-overlay';
import { DynamicOverlayContainer } from './dynamic-overlay-container';
export const DYNAMIC_MAT_DIALOG_PROVIDERS = [
DynamicOverlayContainer,
DynamicOverlay,
DynamicDialog,
DynamicMatDialog,
{
provide: DEFAULT_DIALOG_CONFIG,
useValue: {
...new DialogConfig()
}
}
];
@NgModule( {
imports: [
OverlayModule,
DialogModule,
MatDialogModule
],
providers: DYNAMIC_MAT_DIALOG_PROVIDERS
} )
export class DynamicMatDialogModule {
}

85
ui-ngx/src/app/shared/components/dialog/dynamic/dynamic-dialog.ts

@ -0,0 +1,85 @@
///
/// Copyright © 2016-2025 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { Location } from "@angular/common";
import { Inject, Injectable, Injector, Optional, SkipSelf, TemplateRef } from '@angular/core';
import {
MAT_DIALOG_DEFAULT_OPTIONS,
MAT_DIALOG_SCROLL_STRATEGY,
MatDialog,
MatDialogConfig, MatDialogRef
} from '@angular/material/dialog';
import { DynamicOverlay } from "./dynamic-overlay";
import { DynamicOverlayContainer } from '@shared/components/dialog/dynamic/dynamic-overlay-container';
import { ComponentType, ScrollStrategy } from '@angular/cdk/overlay';
import { DEFAULT_DIALOG_CONFIG, Dialog, DialogConfig } from '@angular/cdk/dialog';
export interface DynamicMatDialogConfig<D> extends MatDialogConfig<D> {
containerElement?: HTMLElement;
}
@Injectable()
export class DynamicMatDialog extends MatDialog {
private _customOverlay: DynamicOverlay;
constructor( _overlay: DynamicOverlay,
_injector: Injector,
@Optional() location: Location,
@Inject( MAT_DIALOG_DEFAULT_OPTIONS ) _defaultOptions: MatDialogConfig,
@Inject( MAT_DIALOG_SCROLL_STRATEGY ) _scrollStrategy: ScrollStrategy,
@Optional() @SkipSelf() _parentDialog:DynamicMatDialog,
_overlayContainer: DynamicOverlayContainer) {
super( _overlay, _injector, location, _defaultOptions, _scrollStrategy, _parentDialog, _overlayContainer );
this._dialog = _injector.get(DynamicDialog);
this._customOverlay = _overlay;
}
public open<T, D = any, R = any>(component: ComponentType<T> | TemplateRef<T>, config?: DynamicMatDialogConfig<D>): MatDialogRef<T, R> {
if (config?.containerElement) {
config.containerElement.style.transform = 'translateZ(0)';
this._customOverlay.setContainerElement( config.containerElement );
}
const ref = super.open(component, config);
if (config?.containerElement) {
ref.afterClosed().subscribe(
{
next: () => {
this._customOverlay.setContainerElement(null);
},
error: () => {
this._customOverlay.setContainerElement(null);
}
}
);
}
return ref;
}
}
@Injectable()
export class DynamicDialog extends Dialog {
constructor( _overlay: DynamicOverlay,
_injector: Injector,
@Inject( DEFAULT_DIALOG_CONFIG ) _defaultOptions: DialogConfig,
@Inject( MAT_DIALOG_SCROLL_STRATEGY ) _scrollStrategy: ScrollStrategy,
@Optional() @SkipSelf() _parentDialog: DynamicDialog,
_overlayContainer: DynamicOverlayContainer) {
super( _overlay, _injector, _defaultOptions, _parentDialog, _overlayContainer, _scrollStrategy );
}
}

27
ui-ngx/src/app/shared/components/dialog/dynamic/dynamic-overlay-container.ts

@ -0,0 +1,27 @@
///
/// Copyright © 2016-2025 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import { OverlayContainer } from "@angular/cdk/overlay";
import { Injectable } from "@angular/core";
@Injectable()
export class DynamicOverlayContainer extends OverlayContainer {
public setContainerElement( containerElement:HTMLElement ):void {
this._containerElement = containerElement;
}
}

62
ui-ngx/src/app/shared/components/dialog/dynamic/dynamic-overlay.ts

@ -0,0 +1,62 @@
///
/// Copyright © 2016-2025 The Thingsboard Authors
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
import {
Overlay,
ScrollStrategyOptions,
OverlayKeyboardDispatcher, OverlayOutsideClickDispatcher, OverlayPositionBuilder
} from '@angular/cdk/overlay';
import { ComponentFactoryResolver, Inject, Injectable, Injector, NgZone } from '@angular/core';
import { DynamicOverlayContainer } from './dynamic-overlay-container';
import { DOCUMENT, Location } from '@angular/common';
import { Directionality } from '@angular/cdk/bidi';
@Injectable()
export class DynamicOverlay extends Overlay {
private _dynamicOverlayContainer: DynamicOverlayContainer;
constructor( scrollStrategies: ScrollStrategyOptions,
_overlayContainer: DynamicOverlayContainer,
_componentFactoryResolver: ComponentFactoryResolver,
_positionBuilder: OverlayPositionBuilder,
_keyboardDispatcher: OverlayKeyboardDispatcher,
_injector: Injector,
_ngZone: NgZone,
@Inject(DOCUMENT) document: Document,
_directionality: Directionality,
_location: Location,
_outsideClickDispatcher: OverlayOutsideClickDispatcher) {
super( scrollStrategies,
_overlayContainer,
_componentFactoryResolver,
_positionBuilder,
_keyboardDispatcher,
_injector,
_ngZone,
document,
_directionality,
_location,
_outsideClickDispatcher);
this._dynamicOverlayContainer = _overlayContainer;
}
public setContainerElement(containerElement:HTMLElement ): void {
this._dynamicOverlayContainer.setContainerElement( containerElement );
}
}

7
ui-ngx/src/app/shared/shared.module.ts

@ -237,6 +237,7 @@ import { StringPatternAutocompleteComponent } from '@shared/components/string-pa
import { TimeUnitInputComponent } from '@shared/components/time-unit-input.component';
import { DateExpirationPipe } from '@shared/pipe/date-expiration.pipe';
import { EntityLimitExceededDialogComponent } from '@shared/components/dialog/entity-limit-exceeded-dialog.component';
import { DynamicMatDialogModule } from '@shared/components/dialog/dynamic/dynamic-dialog.module';
export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) {
return markedOptionsService;
@ -520,7 +521,8 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService)
useFactory: MarkedOptionsFactory,
deps: [MarkedOptionsService]
}
})
}),
DynamicMatDialogModule
],
exports: [
FooterComponent,
@ -726,7 +728,8 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService)
MqttVersionSelectComponent,
PasswordRequirementsTooltipComponent,
TimeUnitInputComponent,
StringPatternAutocompleteComponent
StringPatternAutocompleteComponent,
DynamicMatDialogModule
]
})
export class SharedModule { }

Loading…
Cancel
Save