diff --git a/packages/core/src/render3/di.ts b/packages/core/src/render3/di.ts index d49f92b73a..3cdbc6c6d4 100644 --- a/packages/core/src/render3/di.ts +++ b/packages/core/src/render3/di.ts @@ -152,10 +152,6 @@ export function getOrCreateNodeInjectorForNode( insertBloom(tView.data, tNode); // foundation for node bloom insertBloom(hostView, null); // foundation for cumulative bloom insertBloom(tView.blueprint, null); - - ngDevMode && assertEqual( - tNode.flags === 0 || tNode.flags === TNodeFlags.isComponentHost, true, - 'expected tNode.flags to not be initialized'); } const parentLoc = getParentInjectorLocation(tNode, hostView); diff --git a/packages/core/src/render3/instructions/element.ts b/packages/core/src/render3/instructions/element.ts index 6c8e1eb4a1..c42c9e5860 100644 --- a/packages/core/src/render3/instructions/element.ts +++ b/packages/core/src/render3/instructions/element.ts @@ -10,7 +10,7 @@ import {assertDataInRange, assertDefined, assertEqual} from '../../util/assert'; import {assertHasParent} from '../assert'; import {attachPatchData} from '../context_discovery'; import {registerPostOrderHooks} from '../hooks'; -import {TAttributes, TNodeType} from '../interfaces/node'; +import {TAttributes, TNodeFlags, TNodeType} from '../interfaces/node'; import {RElement} from '../interfaces/renderer'; import {StylingMapArray, TStylingContext} from '../interfaces/styling'; import {isContentQueryHost, isDirectiveHost} from '../interfaces/type_checks'; @@ -64,7 +64,9 @@ export function ɵɵelementStart( } } - renderInitialStyling(renderer, native, tNode); + if ((tNode.flags & TNodeFlags.hasInitialStyling) === TNodeFlags.hasInitialStyling) { + renderInitialStyling(renderer, native, tNode); + } appendChild(native, tNode, lView); diff --git a/packages/core/src/render3/instructions/lview_debug.ts b/packages/core/src/render3/instructions/lview_debug.ts index 779416cecd..fe8e0bcc55 100644 --- a/packages/core/src/render3/instructions/lview_debug.ts +++ b/packages/core/src/render3/instructions/lview_debug.ts @@ -162,6 +162,7 @@ export const TNodeConstructor = class TNode implements ITNode { if (this.flags & TNodeFlags.hasClassInput) flags.push('TNodeFlags.hasClassInput'); if (this.flags & TNodeFlags.hasContentQuery) flags.push('TNodeFlags.hasContentQuery'); if (this.flags & TNodeFlags.hasStyleInput) flags.push('TNodeFlags.hasStyleInput'); + if (this.flags & TNodeFlags.hasInitialStyling) flags.push('TNodeFlags.hasInitialStyling'); if (this.flags & TNodeFlags.isComponentHost) flags.push('TNodeFlags.isComponentHost'); if (this.flags & TNodeFlags.isDirectiveHost) flags.push('TNodeFlags.isDirectiveHost'); if (this.flags & TNodeFlags.isDetached) flags.push('TNodeFlags.isDetached'); diff --git a/packages/core/src/render3/instructions/shared.ts b/packages/core/src/render3/instructions/shared.ts index 8ca5f47cc4..e1d43ebeb6 100644 --- a/packages/core/src/render3/instructions/shared.ts +++ b/packages/core/src/render3/instructions/shared.ts @@ -1232,7 +1232,7 @@ function findDirectiveMatches( */ export function markAsComponentHost(tView: TView, hostTNode: TNode): void { ngDevMode && assertFirstTemplatePass(tView); - hostTNode.flags = TNodeFlags.isComponentHost; + hostTNode.flags |= TNodeFlags.isComponentHost; (tView.components || (tView.components = ngDevMode ? new TViewComponents() : [ ])).push(hostTNode.index); } @@ -1279,16 +1279,11 @@ function saveNameToExportMap( * @param index the initial index */ export function initNodeFlags(tNode: TNode, index: number, numberOfDirectives: number) { - const flags = tNode.flags; - ngDevMode && assertEqual( - flags === 0 || flags === TNodeFlags.isComponentHost, true, - 'expected node flags to not be initialized'); - ngDevMode && assertNotEqual( numberOfDirectives, tNode.directiveEnd - tNode.directiveStart, 'Reached the max number of directives'); + tNode.flags |= TNodeFlags.isDirectiveHost; // When the first directive is created on a node, save the index - tNode.flags = (flags & TNodeFlags.isComponentHost) | TNodeFlags.isDirectiveHost; tNode.directiveStart = index; tNode.directiveEnd = index + numberOfDirectives; tNode.providerIndexes = index; diff --git a/packages/core/src/render3/instructions/styling.ts b/packages/core/src/render3/instructions/styling.ts index f299bed4d6..84f24bb6c9 100644 --- a/packages/core/src/render3/instructions/styling.ts +++ b/packages/core/src/render3/instructions/styling.ts @@ -8,7 +8,7 @@ import {SafeValue} from '../../sanitization/bypass'; import {StyleSanitizeFn} from '../../sanitization/style_sanitizer'; import {setInputsForProperty} from '../instructions/shared'; -import {AttributeMarker, TAttributes, TNode, TNodeType} from '../interfaces/node'; +import {AttributeMarker, TAttributes, TNode, TNodeFlags, TNodeType} from '../interfaces/node'; import {RElement} from '../interfaces/renderer'; import {StylingMapArray, StylingMapArrayIndex, TStylingContext} from '../interfaces/styling'; import {BINDING_INDEX, LView, RENDERER} from '../interfaces/view'; @@ -474,6 +474,10 @@ export function registerInitialStylingOnTNode( updateRawValueOnContext(tNode.styles, stylingMapToString(styles, false)); } + if (hasAdditionalInitialStyling) { + tNode.flags |= TNodeFlags.hasInitialStyling; + } + return hasAdditionalInitialStyling; } diff --git a/packages/core/src/render3/interfaces/node.ts b/packages/core/src/render3/interfaces/node.ts index ec563f633b..688784124c 100644 --- a/packages/core/src/render3/interfaces/node.ts +++ b/packages/core/src/render3/interfaces/node.ts @@ -65,8 +65,11 @@ export const enum TNodeFlags { /** This bit is set if the node has any "style" inputs */ hasStyleInput = 0b00100000, + /** This bit is set if the node has initial styling */ + hasInitialStyling = 0b01000000, + /** This bit is set if the node has been detached by i18n */ - isDetached = 0b01000000, + isDetached = 0b10000000, } /** diff --git a/packages/core/test/acceptance/styling_spec.ts b/packages/core/test/acceptance/styling_spec.ts index feca76c020..ceb3f07043 100644 --- a/packages/core/test/acceptance/styling_spec.ts +++ b/packages/core/test/acceptance/styling_spec.ts @@ -113,6 +113,34 @@ describe('styling', () => { expect(outer.textContent.trim()).toEqual('outer'); }); + it('should render initial styling for repeated nodes that a component host', () => { + @Component({ + selector: '[comp]', + template: '', + }) + class Comp { + } + + @Component({ + template: ` + +

A

+
+ ` + }) + class App { + items = [1, 2, 3]; + } + + TestBed.configureTestingModule({ + declarations: [App, Comp], + }); + const fixture = TestBed.createComponent(App); + fixture.detectChanges(); + + expect(fixture.debugElement.queryAll(By.css('.a')).length).toBe(3); + }); + it('should do nothing for empty style bindings', () => { @Component({template: '
'}) class App {