MOBILE-3320 dom: Store instances using a WeakMap
parent
345ff293c1
commit
1e82b7796c
|
@ -40,13 +40,10 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy {
|
||||||
protected items: CoreContextMenuItemComponent[] = [];
|
protected items: CoreContextMenuItemComponent[] = [];
|
||||||
protected itemsMovedToParent: CoreContextMenuItemComponent[] = [];
|
protected itemsMovedToParent: CoreContextMenuItemComponent[] = [];
|
||||||
protected itemsChangedStream: Subject<void>; // Stream to update the hideMenu boolean when items change.
|
protected itemsChangedStream: Subject<void>; // Stream to update the hideMenu boolean when items change.
|
||||||
protected instanceId: string;
|
|
||||||
protected parentContextMenu?: CoreContextMenuComponent;
|
protected parentContextMenu?: CoreContextMenuComponent;
|
||||||
protected expanded = false;
|
protected expanded = false;
|
||||||
|
|
||||||
constructor(
|
constructor(elementRef: ElementRef) {
|
||||||
elementRef: ElementRef,
|
|
||||||
) {
|
|
||||||
// Create the stream and subscribe to it. We ignore successive changes during 250ms.
|
// Create the stream and subscribe to it. We ignore successive changes during 250ms.
|
||||||
this.itemsChangedStream = new Subject<void>();
|
this.itemsChangedStream = new Subject<void>();
|
||||||
this.itemsChangedStream.pipe(auditTime(250));
|
this.itemsChangedStream.pipe(auditTime(250));
|
||||||
|
@ -61,7 +58,7 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy {
|
||||||
// Calculate the unique ID.
|
// Calculate the unique ID.
|
||||||
this.uniqueId = 'core-context-menu-' + CoreUtils.getUniqueId('CoreContextMenuComponent');
|
this.uniqueId = 'core-context-menu-' + CoreUtils.getUniqueId('CoreContextMenuComponent');
|
||||||
|
|
||||||
this.instanceId = CoreDomUtils.storeInstanceByElement(elementRef.nativeElement, this);
|
CoreDomUtils.storeInstanceByElement(elementRef.nativeElement, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -202,7 +199,6 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy {
|
||||||
* Component destroyed.
|
* Component destroyed.
|
||||||
*/
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
CoreDomUtils.removeInstanceById(this.instanceId);
|
|
||||||
this.removeMergedItems();
|
this.removeMergedItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,13 +62,13 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy {
|
||||||
protected forceHidden = false;
|
protected forceHidden = false;
|
||||||
protected logger: CoreLogger;
|
protected logger: CoreLogger;
|
||||||
protected movedChildren?: Node[];
|
protected movedChildren?: Node[];
|
||||||
protected instanceId: string;
|
|
||||||
protected mergedContextMenu?: CoreContextMenuComponent;
|
protected mergedContextMenu?: CoreContextMenuComponent;
|
||||||
|
|
||||||
constructor(element: ElementRef) {
|
constructor(element: ElementRef) {
|
||||||
this.element = element.nativeElement;
|
this.element = element.nativeElement;
|
||||||
this.logger = CoreLogger.getInstance('CoreNavBarButtonsComponent');
|
this.logger = CoreLogger.getInstance('CoreNavBarButtonsComponent');
|
||||||
this.instanceId = CoreDomUtils.storeInstanceByElement(this.element, this);
|
|
||||||
|
CoreDomUtils.storeInstanceByElement(this.element, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -138,9 +138,8 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Both containers have a context menu. Merge them to prevent having 2 menus at the same time.
|
// Both containers have a context menu. Merge them to prevent having 2 menus at the same time.
|
||||||
const mainContextMenuInstance: CoreContextMenuComponent = CoreDomUtils.getInstanceByElement(mainContextMenu);
|
const mainContextMenuInstance = CoreDomUtils.getInstanceByElement<CoreContextMenuComponent>(mainContextMenu);
|
||||||
const secondaryContextMenuInstance: CoreContextMenuComponent =
|
const secondaryContextMenuInstance = CoreDomUtils.getInstanceByElement<CoreContextMenuComponent>(secondaryContextMenu);
|
||||||
CoreDomUtils.getInstanceByElement(secondaryContextMenu);
|
|
||||||
|
|
||||||
// Check that both context menus belong to the same core-tab. We shouldn't merge menus from different tabs.
|
// Check that both context menus belong to the same core-tab. We shouldn't merge menus from different tabs.
|
||||||
if (mainContextMenuInstance && secondaryContextMenuInstance) {
|
if (mainContextMenuInstance && secondaryContextMenuInstance) {
|
||||||
|
@ -247,8 +246,6 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy {
|
||||||
* Component destroyed.
|
* Component destroyed.
|
||||||
*/
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
CoreDomUtils.removeInstanceById(this.instanceId);
|
|
||||||
|
|
||||||
// This component was destroyed, remove all the buttons that were moved.
|
// This component was destroyed, remove all the buttons that were moved.
|
||||||
// The buttons can be moved outside of the current page, that's why we need to manually destroy them.
|
// The buttons can be moved outside of the current page, that's why we need to manually destroy them.
|
||||||
// There's no need to destroy context menu items that were merged because they weren't moved from their DOM position.
|
// There's no need to destroy context menu items that were merged because they weren't moved from their DOM position.
|
||||||
|
|
|
@ -150,7 +150,7 @@ export class CoreTabsOutletComponent extends CoreTabsBaseComponent<CoreTabsOutle
|
||||||
const elements = this.ionTabs!.outlet.nativeEl.querySelectorAll('core-navbar-buttons');
|
const elements = this.ionTabs!.outlet.nativeEl.querySelectorAll('core-navbar-buttons');
|
||||||
const domUtils = CoreDomUtils.instance;
|
const domUtils = CoreDomUtils.instance;
|
||||||
elements.forEach((element) => {
|
elements.forEach((element) => {
|
||||||
const instance: CoreNavBarButtonsComponent = domUtils.getInstanceByElement(element);
|
const instance = domUtils.getInstanceByElement<CoreNavBarButtonsComponent>(element);
|
||||||
|
|
||||||
if (instance) {
|
if (instance) {
|
||||||
const pagetagName = element.closest('.ion-page')?.tagName;
|
const pagetagName = element.closest('.ion-page')?.tagName;
|
||||||
|
|
|
@ -144,7 +144,7 @@ export class CoreTabComponent implements OnInit, OnDestroy, CoreTabBase {
|
||||||
protected showHideNavBarButtons(show: boolean): void {
|
protected showHideNavBarButtons(show: boolean): void {
|
||||||
const elements = this.element.querySelectorAll('core-navbar-buttons');
|
const elements = this.element.querySelectorAll('core-navbar-buttons');
|
||||||
elements.forEach((element) => {
|
elements.forEach((element) => {
|
||||||
const instance: CoreNavBarButtonsComponent = CoreDomUtils.getInstanceByElement(element);
|
const instance = CoreDomUtils.getInstanceByElement<CoreNavBarButtonsComponent>(element);
|
||||||
|
|
||||||
if (instance) {
|
if (instance) {
|
||||||
instance.forceHide(!show);
|
instance.forceHide(!show);
|
||||||
|
|
|
@ -53,9 +53,7 @@ export class CoreDomUtilsProvider {
|
||||||
protected template: HTMLTemplateElement = document.createElement('template'); // A template element to convert HTML to element.
|
protected template: HTMLTemplateElement = document.createElement('template'); // A template element to convert HTML to element.
|
||||||
|
|
||||||
protected matchesFunctionName?: string; // Name of the "matches" function to use when simulating a closest call.
|
protected matchesFunctionName?: string; // Name of the "matches" function to use when simulating a closest call.
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
protected instances: WeakMap<Element, unknown> = new WeakMap(); // Store component/directive instances indexed by element.
|
||||||
protected instances: {[id: string]: any} = {}; // Store component/directive instances by id.
|
|
||||||
protected lastInstanceId = 0;
|
|
||||||
protected debugDisplay = false; // Whether to display debug messages. Store it in a variable to make it synchronous.
|
protected debugDisplay = false; // Whether to display debug messages. Store it in a variable to make it synchronous.
|
||||||
protected displayedAlerts: Record<string, HTMLIonAlertElement> = {}; // To prevent duplicated alerts.
|
protected displayedAlerts: Record<string, HTMLIonAlertElement> = {}; // To prevent duplicated alerts.
|
||||||
protected activeLoadingModals: CoreIonLoadingElement[] = [];
|
protected activeLoadingModals: CoreIonLoadingElement[] = [];
|
||||||
|
@ -706,11 +704,8 @@ export class CoreDomUtilsProvider {
|
||||||
* @param element The root element of the component/directive.
|
* @param element The root element of the component/directive.
|
||||||
* @return The instance, undefined if not found.
|
* @return The instance, undefined if not found.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
getInstanceByElement<T = unknown>(element: Element): T | undefined {
|
||||||
getInstanceByElement(element: Element): any {
|
return this.instances.get(element) as T;
|
||||||
const id = element.getAttribute(this.INSTANCE_ID_ATTR_NAME);
|
|
||||||
|
|
||||||
return id && this.instances[id];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1629,16 +1624,9 @@ export class CoreDomUtilsProvider {
|
||||||
*
|
*
|
||||||
* @param element The root element of the component/directive.
|
* @param element The root element of the component/directive.
|
||||||
* @param instance The instance to store.
|
* @param instance The instance to store.
|
||||||
* @return ID to identify the instance.
|
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
storeInstanceByElement(element: Element, instance: unknown): void {
|
||||||
storeInstanceByElement(element: Element, instance: any): string {
|
this.instances.set(element, instance);
|
||||||
const id = String(this.lastInstanceId++);
|
|
||||||
|
|
||||||
element.setAttribute(this.INSTANCE_ID_ATTR_NAME, id);
|
|
||||||
this.instances[id] = instance;
|
|
||||||
|
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue