mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(overlay): make config immutable for existing refs (#7376)
This changes makes the OverlayConfig instance in OverlatRef immutable. Calling `getConfig` will now return a clone of the config to make clear that it cannot be modified directly to change the state of the overlay. This also updates the `updateSize` method to accept a partial config to apply to the existing config (and make a new config instance). This *also* tightens up the typings on Portal.attach BREAKING CHANGE: OverlayRef.getConfig returns an immutable version of the config object. BREAKING CHANGE: OverlayRef.updateSize now accepts a OverlaySizeConfig rather than being based on the existing config object.
This commit is contained in:
committed by
tinayuangao
parent
23c09b488d
commit
2dbc76631d
@@ -333,7 +333,7 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges {
|
||||
}
|
||||
|
||||
this._position.withDirection(this.dir);
|
||||
this._overlayRef.getConfig().direction = this.dir;
|
||||
this._overlayRef.setDirection(this.dir);
|
||||
this._document.addEventListener('keydown', this._escapeListener);
|
||||
|
||||
if (!this._overlayRef.hasAttached()) {
|
||||
|
||||
@@ -6,15 +6,21 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {NgZone} from '@angular/core';
|
||||
import {PortalOutlet, Portal} from '@angular/cdk/portal';
|
||||
import {OverlayConfig} from './overlay-config';
|
||||
import {OverlayKeyboardDispatcher} from './keyboard/overlay-keyboard-dispatcher';
|
||||
import {Direction} from '@angular/cdk/bidi';
|
||||
import {ComponentPortal, Portal, PortalOutlet, TemplatePortal} from '@angular/cdk/portal';
|
||||
import {ComponentRef, EmbeddedViewRef, NgZone} from '@angular/core';
|
||||
import {Observable} from 'rxjs/Observable';
|
||||
import {Subject} from 'rxjs/Subject';
|
||||
import {take} from 'rxjs/operators/take';
|
||||
import {Subject} from 'rxjs/Subject';
|
||||
import {OverlayKeyboardDispatcher} from './keyboard/overlay-keyboard-dispatcher';
|
||||
import {OverlayConfig} from './overlay-config';
|
||||
|
||||
|
||||
/** An object where all of its properties cannot be written. */
|
||||
export type ImmutableObject<T> = {
|
||||
readonly [P in keyof T]: T[P];
|
||||
};
|
||||
|
||||
/**
|
||||
* Reference to an overlay that has been created with the Overlay service.
|
||||
* Used to manipulate or dispose of said overlay.
|
||||
@@ -31,7 +37,7 @@ export class OverlayRef implements PortalOutlet {
|
||||
constructor(
|
||||
private _portalOutlet: PortalOutlet,
|
||||
private _pane: HTMLElement,
|
||||
private _config: OverlayConfig,
|
||||
private _config: ImmutableObject<OverlayConfig>,
|
||||
private _ngZone: NgZone,
|
||||
private _keyboardDispatcher: OverlayKeyboardDispatcher) {
|
||||
|
||||
@@ -45,8 +51,14 @@ export class OverlayRef implements PortalOutlet {
|
||||
return this._pane;
|
||||
}
|
||||
|
||||
attach<T>(portal: ComponentPortal<T>): ComponentRef<T>;
|
||||
attach<T>(portal: TemplatePortal<T>): EmbeddedViewRef<T>;
|
||||
attach(portal: any): any;
|
||||
|
||||
/**
|
||||
* Attaches the overlay to a portal instance and adds the backdrop.
|
||||
* Attaches content, given via a Portal, to the overlay.
|
||||
* If the overlay is configured to have a backdrop, it will be created.
|
||||
*
|
||||
* @param portal Portal instance to which to attach the overlay.
|
||||
* @returns The portal attachment result.
|
||||
*/
|
||||
@@ -59,8 +71,8 @@ export class OverlayRef implements PortalOutlet {
|
||||
|
||||
// Update the pane element with the given configuration.
|
||||
this._updateStackingOrder();
|
||||
this.updateSize();
|
||||
this.updateDirection();
|
||||
this._updateElementSize();
|
||||
this._updateElementDirection();
|
||||
|
||||
if (this._config.scrollStrategy) {
|
||||
this._config.scrollStrategy.enable();
|
||||
@@ -133,9 +145,7 @@ export class OverlayRef implements PortalOutlet {
|
||||
return detachmentResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up the overlay from the DOM.
|
||||
*/
|
||||
/** Cleans up the overlay from the DOM. */
|
||||
dispose(): void {
|
||||
const isAttached = this.hasAttached();
|
||||
|
||||
@@ -161,16 +171,12 @@ export class OverlayRef implements PortalOutlet {
|
||||
this._detachments.complete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the overlay has been attached.
|
||||
*/
|
||||
/** Whether the overlay has attached content. */
|
||||
hasAttached(): boolean {
|
||||
return this._portalOutlet.hasAttached();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an observable that emits when the backdrop has been clicked.
|
||||
*/
|
||||
/** Gets an observable that emits when the backdrop has been clicked. */
|
||||
backdropClick(): Observable<void> {
|
||||
return this._backdropClick.asObservable();
|
||||
}
|
||||
@@ -190,9 +196,7 @@ export class OverlayRef implements PortalOutlet {
|
||||
return this._keydownEvents.asObservable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current config of the overlay.
|
||||
*/
|
||||
/** Gets the the current overlay configuration, which is immutable. */
|
||||
getConfig(): OverlayConfig {
|
||||
return this._config;
|
||||
}
|
||||
@@ -204,13 +208,25 @@ export class OverlayRef implements PortalOutlet {
|
||||
}
|
||||
}
|
||||
|
||||
/** Update the size properties of the overlay. */
|
||||
updateSize(sizeConfig: OverlaySizeConfig) {
|
||||
this._config = {...this._config, ...sizeConfig};
|
||||
this._updateElementSize();
|
||||
}
|
||||
|
||||
/** Sets the LTR/RTL direction for the overlay. */
|
||||
setDirection(dir: Direction) {
|
||||
this._config = {...this._config, direction: dir};
|
||||
this._updateElementDirection();
|
||||
}
|
||||
|
||||
/** Updates the text direction of the overlay panel. */
|
||||
private updateDirection() {
|
||||
private _updateElementDirection() {
|
||||
this._pane.setAttribute('dir', this._config.direction!);
|
||||
}
|
||||
|
||||
/** Updates the size of the overlay based on the overlay config. */
|
||||
updateSize() {
|
||||
/** Updates the size of the overlay element based on the overlay config. */
|
||||
private _updateElementSize() {
|
||||
if (this._config.width || this._config.width === 0) {
|
||||
this._pane.style.width = formatCssUnit(this._config.width);
|
||||
}
|
||||
@@ -259,10 +275,12 @@ export class OverlayRef implements PortalOutlet {
|
||||
this._backdropElement.addEventListener('click', () => this._backdropClick.next(null));
|
||||
|
||||
// Add class to fade-in the backdrop after one frame.
|
||||
requestAnimationFrame(() => {
|
||||
if (this._backdropElement) {
|
||||
this._backdropElement.classList.add('cdk-overlay-backdrop-showing');
|
||||
}
|
||||
this._ngZone.runOutsideAngular(() => {
|
||||
requestAnimationFrame(() => {
|
||||
if (this._backdropElement) {
|
||||
this._backdropElement.classList.add('cdk-overlay-backdrop-showing');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -323,3 +341,14 @@ export class OverlayRef implements PortalOutlet {
|
||||
function formatCssUnit(value: number | string) {
|
||||
return typeof value === 'string' ? value as string : `${value}px`;
|
||||
}
|
||||
|
||||
|
||||
/** Size properties for an overlay. */
|
||||
export interface OverlaySizeConfig {
|
||||
width?: number | string;
|
||||
height?: number | string;
|
||||
minWidth?: number | string;
|
||||
minHeight?: number | string;
|
||||
maxWidth?: number | string;
|
||||
maxHeight?: number | string;
|
||||
}
|
||||
|
||||
@@ -181,6 +181,10 @@ export abstract class BasePortalOutlet implements PortalOutlet {
|
||||
return !!this._attachedPortal;
|
||||
}
|
||||
|
||||
attach<T>(portal: ComponentPortal<T>): ComponentRef<T>;
|
||||
attach<T>(portal: TemplatePortal<T>): EmbeddedViewRef<T>;
|
||||
attach(portal: any): any;
|
||||
|
||||
/** Attaches a portal. */
|
||||
attach(portal: Portal<any>): any {
|
||||
if (!portal) {
|
||||
|
||||
@@ -458,8 +458,7 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
|
||||
this._overlayRef = this._overlay.create(this._getOverlayConfig());
|
||||
} else {
|
||||
/** Update the panel width, in case the host width has changed */
|
||||
this._overlayRef.getConfig().width = this._getHostWidth();
|
||||
this._overlayRef.updateSize();
|
||||
this._overlayRef.updateSize({width: this._getHostWidth()});
|
||||
}
|
||||
|
||||
if (this._overlayRef && !this._overlayRef.hasAttached()) {
|
||||
|
||||
Reference in New Issue
Block a user