@@ -9,11 +9,12 @@ import { attachToEventDelegator as attachNavigationManagerToEventDelegator } fro
9
9
import { applyAnyDeferredValue , tryApplySpecialProperty } from './DomSpecialPropertyUtil' ;
10
10
const sharedTemplateElemForParsing = document . createElement ( 'template' ) ;
11
11
const sharedSvgElemForParsing = document . createElementNS ( 'http://www.w3.org/2000/svg' , 'g' ) ;
12
- const elementsToClearOnRootComponentRender : { [ componentId : number ] : LogicalElement } = { } ;
12
+ const elementsToClearOnRootComponentRender = new Set < LogicalElement > ( ) ;
13
13
const internalAttributeNamePrefix = '__internal_' ;
14
14
const eventPreventDefaultAttributeNamePrefix = 'preventDefault_' ;
15
15
const eventStopPropagationAttributeNamePrefix = 'stopPropagation_' ;
16
16
const interactiveRootComponentPropname = Symbol ( ) ;
17
+ const preserveContentOnDisposalPropname = Symbol ( ) ;
17
18
18
19
export class BrowserRenderer {
19
20
public eventDelegator : EventDelegator ;
@@ -47,7 +48,7 @@ export class BrowserRenderer {
47
48
// If we want to preserve existing HTML content of the root element, we don't apply the mechanism for
48
49
// clearing existing children. Rendered content will then append rather than replace the existing HTML content.
49
50
if ( ! appendContent ) {
50
- elementsToClearOnRootComponentRender [ componentId ] = element ;
51
+ elementsToClearOnRootComponentRender . add ( element ) ;
51
52
}
52
53
}
53
54
@@ -58,15 +59,13 @@ export class BrowserRenderer {
58
59
}
59
60
60
61
// On the first render for each root component, clear any existing content (e.g., prerendered)
61
- const rootElementToClear = elementsToClearOnRootComponentRender [ componentId ] ;
62
- if ( rootElementToClear ) {
63
- delete elementsToClearOnRootComponentRender [ componentId ] ;
64
- emptyLogicalElement ( rootElementToClear ) ;
62
+ if ( elementsToClearOnRootComponentRender . delete ( element ) ) {
63
+ emptyLogicalElement ( element ) ;
65
64
66
- if ( rootElementToClear instanceof Comment ) {
65
+ if ( element instanceof Comment ) {
67
66
// We sanitize start comments by removing all the information from it now that we don't need it anymore
68
67
// as it adds noise to the DOM.
69
- rootElementToClear . textContent = '!' ;
68
+ element . textContent = '!' ;
70
69
}
71
70
}
72
71
@@ -88,7 +87,12 @@ export class BrowserRenderer {
88
87
// component was added.
89
88
const logicalElement = this . childComponentLocations [ componentId ] ;
90
89
markAsInteractiveRootComponentElement ( logicalElement , false ) ;
91
- emptyLogicalElement ( logicalElement ) ;
90
+
91
+ if ( shouldPreserveContentOnInteractiveComponentDisposal ( logicalElement ) ) {
92
+ elementsToClearOnRootComponentRender . add ( logicalElement ) ;
93
+ } else {
94
+ emptyLogicalElement ( logicalElement ) ;
95
+ }
92
96
}
93
97
94
98
delete this . childComponentLocations [ componentId ] ;
@@ -377,6 +381,14 @@ export function isInteractiveRootComponentElement(element: LogicalElement): bool
377
381
return element [ interactiveRootComponentPropname ] ;
378
382
}
379
383
384
+ export function setShouldPreserveContentOnInteractiveComponentDisposal ( element : LogicalElement , shouldPreserve : boolean ) {
385
+ element [ preserveContentOnDisposalPropname ] = shouldPreserve ;
386
+ }
387
+
388
+ function shouldPreserveContentOnInteractiveComponentDisposal ( element : LogicalElement ) : boolean {
389
+ return element [ preserveContentOnDisposalPropname ] === true ;
390
+ }
391
+
380
392
export interface ComponentDescriptor {
381
393
start : Node ;
382
394
end : Node ;
0 commit comments