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 itemsMovedToParent: CoreContextMenuItemComponent[] = [];
|
||||
protected itemsChangedStream: Subject<void>; // Stream to update the hideMenu boolean when items change.
|
||||
protected instanceId: string;
|
||||
protected parentContextMenu?: CoreContextMenuComponent;
|
||||
protected expanded = false;
|
||||
|
||||
constructor(
|
||||
elementRef: ElementRef,
|
||||
) {
|
||||
constructor(elementRef: ElementRef) {
|
||||
// Create the stream and subscribe to it. We ignore successive changes during 250ms.
|
||||
this.itemsChangedStream = new Subject<void>();
|
||||
this.itemsChangedStream.pipe(auditTime(250));
|
||||
|
@ -61,7 +58,7 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy {
|
|||
// Calculate the unique ID.
|
||||
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.
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
CoreDomUtils.removeInstanceById(this.instanceId);
|
||||
this.removeMergedItems();
|
||||
}
|
||||
|
||||
|
|
|
@ -62,13 +62,13 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy {
|
|||
protected forceHidden = false;
|
||||
protected logger: CoreLogger;
|
||||
protected movedChildren?: Node[];
|
||||
protected instanceId: string;
|
||||
protected mergedContextMenu?: CoreContextMenuComponent;
|
||||
|
||||
constructor(element: ElementRef) {
|
||||
this.element = element.nativeElement;
|
||||
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.
|
||||
const mainContextMenuInstance: CoreContextMenuComponent = CoreDomUtils.getInstanceByElement(mainContextMenu);
|
||||
const secondaryContextMenuInstance: CoreContextMenuComponent =
|
||||
CoreDomUtils.getInstanceByElement(secondaryContextMenu);
|
||||
const mainContextMenuInstance = CoreDomUtils.getInstanceByElement<CoreContextMenuComponent>(mainContextMenu);
|
||||
const secondaryContextMenuInstance = CoreDomUtils.getInstanceByElement<CoreContextMenuComponent>(secondaryContextMenu);
|
||||
|
||||
// Check that both context menus belong to the same core-tab. We shouldn't merge menus from different tabs.
|
||||
if (mainContextMenuInstance && secondaryContextMenuInstance) {
|
||||
|
@ -247,8 +246,6 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy {
|
|||
* Component destroyed.
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
CoreDomUtils.removeInstanceById(this.instanceId);
|
||||
|
||||
// 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.
|
||||
// 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 domUtils = CoreDomUtils.instance;
|
||||
elements.forEach((element) => {
|
||||
const instance: CoreNavBarButtonsComponent = domUtils.getInstanceByElement(element);
|
||||
const instance = domUtils.getInstanceByElement<CoreNavBarButtonsComponent>(element);
|
||||
|
||||
if (instance) {
|
||||
const pagetagName = element.closest('.ion-page')?.tagName;
|
||||
|
|
|
@ -144,7 +144,7 @@ export class CoreTabComponent implements OnInit, OnDestroy, CoreTabBase {
|
|||
protected showHideNavBarButtons(show: boolean): void {
|
||||
const elements = this.element.querySelectorAll('core-navbar-buttons');
|
||||
elements.forEach((element) => {
|
||||
const instance: CoreNavBarButtonsComponent = CoreDomUtils.getInstanceByElement(element);
|
||||
const instance = CoreDomUtils.getInstanceByElement<CoreNavBarButtonsComponent>(element);
|
||||
|
||||
if (instance) {
|
||||
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 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: {[id: string]: any} = {}; // Store component/directive instances by id.
|
||||
protected lastInstanceId = 0;
|
||||
protected instances: WeakMap<Element, unknown> = new WeakMap(); // Store component/directive instances indexed by element.
|
||||
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 activeLoadingModals: CoreIonLoadingElement[] = [];
|
||||
|
@ -706,11 +704,8 @@ export class CoreDomUtilsProvider {
|
|||
* @param element The root element of the component/directive.
|
||||
* @return The instance, undefined if not found.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
getInstanceByElement(element: Element): any {
|
||||
const id = element.getAttribute(this.INSTANCE_ID_ATTR_NAME);
|
||||
|
||||
return id && this.instances[id];
|
||||
getInstanceByElement<T = unknown>(element: Element): T | undefined {
|
||||
return this.instances.get(element) as T;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1629,16 +1624,9 @@ export class CoreDomUtilsProvider {
|
|||
*
|
||||
* @param element The root element of the component/directive.
|
||||
* @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: any): string {
|
||||
const id = String(this.lastInstanceId++);
|
||||
|
||||
element.setAttribute(this.INSTANCE_ID_ATTR_NAME, id);
|
||||
this.instances[id] = instance;
|
||||
|
||||
return id;
|
||||
storeInstanceByElement(element: Element, instance: unknown): void {
|
||||
this.instances.set(element, instance);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue