Skip to content

Commit dc9f0af

Browse files
marclavalbenlesh
authored andcommitted
fix(ivy): static host classes and styles should work on root component (angular#28926)
PR Close angular#28926
1 parent 8f8f9a6 commit dc9f0af

File tree

5 files changed

+43
-40
lines changed

5 files changed

+43
-40
lines changed

integration/_payload-limits.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"master": {
1313
"uncompressed": {
1414
"runtime": 1440,
15-
"main": 13019,
15+
"main": 13659,
1616
"polyfills": 38390
1717
}
1818
}
@@ -34,4 +34,4 @@
3434
}
3535
}
3636
}
37-
}
37+
}

packages/core/src/render3/component.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,10 @@ import {ComponentDef, ComponentType, RenderFlags} from './interfaces/definition'
2222
import {TElementNode, TNode, TNodeFlags, TNodeType} from './interfaces/node';
2323
import {PlayerHandler} from './interfaces/player';
2424
import {RElement, Renderer3, RendererFactory3, domRendererFactory3} from './interfaces/renderer';
25-
import {CONTEXT, FLAGS, HEADER_OFFSET, LView, LViewFlags, RootContext, RootContextFlags, TVIEW} from './interfaces/view';
25+
import {CONTEXT, FLAGS, HEADER_OFFSET, HOST, LView, LViewFlags, RENDERER, RootContext, RootContextFlags, TVIEW} from './interfaces/view';
2626
import {applyOnCreateInstructions} from './node_util';
2727
import {enterView, getPreviousOrParentTNode, leaveView, resetComponentState, setCurrentDirectiveDef} from './state';
28+
import {renderInitialClasses, renderInitialStyles} from './styling/class_and_style_bindings';
2829
import {publishDefaultGlobalUtils} from './util/global_utils';
2930
import {defaultScheduler, renderStringify} from './util/misc_utils';
3031
import {getRootContext, getRootView} from './util/view_traversal_utils';
@@ -201,14 +202,20 @@ export function createRootComponent<T>(
201202

202203
hostFeatures && hostFeatures.forEach((feature) => feature(component, componentDef));
203204

205+
const rootTNode = getPreviousOrParentTNode();
204206
if (tView.firstTemplatePass && componentDef.hostBindings) {
205-
const rootTNode = getPreviousOrParentTNode();
206207
const expando = tView.expandoInstructions !;
207208
invokeHostBindingsInCreationMode(
208209
componentDef, expando, component, rootTNode, tView.firstTemplatePass);
209210
rootTNode.onElementCreationFns && applyOnCreateInstructions(rootTNode);
210211
}
211212

213+
if (rootTNode.stylingTemplate) {
214+
const native = componentView[HOST] !as RElement;
215+
renderInitialClasses(native, rootTNode.stylingTemplate, componentView[RENDERER]);
216+
renderInitialStyles(native, rootTNode.stylingTemplate, componentView[RENDERER]);
217+
}
218+
212219
return component;
213220
}
214221

packages/core/test/acceptance/integration_spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,18 @@ describe('acceptance integration tests', () => {
9797
expect(subInstance.dirs.first).toBeAnInstanceOf(SomeDir);
9898
});
9999

100+
it('should render host class and style on the root component', () => {
101+
@Component({template: '...', host: {class: 'foo', style: 'color: red'}})
102+
class MyApp {
103+
}
104+
105+
TestBed.configureTestingModule({declarations: [MyApp]});
106+
const fixture = TestBed.createComponent(MyApp);
107+
const element = fixture.nativeElement;
108+
fixture.detectChanges();
109+
110+
expect(element.style['color']).toEqual('red');
111+
expect(element.classList.contains('foo')).toBeTruthy();
112+
});
113+
100114
});

packages/core/test/bundling/hello_world/bundle.golden_symbols.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@
9898
{
9999
"name": "RENDERER_FACTORY"
100100
},
101+
{
102+
"name": "RendererStyleFlags3"
103+
},
101104
{
102105
"name": "SANITIZER"
103106
},
@@ -410,6 +413,15 @@
410413
{
411414
"name": "renderEmbeddedTemplate"
412415
},
416+
{
417+
"name": "renderInitialClasses"
418+
},
419+
{
420+
"name": "renderInitialStyles"
421+
},
422+
{
423+
"name": "renderInitialStylingValues"
424+
},
413425
{
414426
"name": "renderStringify"
415427
},
@@ -419,6 +431,9 @@
419431
{
420432
"name": "setBindingRoot"
421433
},
434+
{
435+
"name": "setClass"
436+
},
422437
{
423438
"name": "setCurrentDirectiveDef"
424439
},
@@ -440,6 +455,9 @@
440455
{
441456
"name": "setPreviousOrParentTNode"
442457
},
458+
{
459+
"name": "setStyle"
460+
},
443461
{
444462
"name": "setTNodeAndViewData"
445463
},

tools/material-ci/angular_material_test_blocklist.js

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -621,46 +621,10 @@ window.testBlocklist = {
621621
"error": "TypeError: Cannot read property 'nativeElement' of null",
622622
"notes": "FW-1059: DebugNode.query should query nodes in the logical tree"
623623
},
624-
"MatDatepicker with MatNativeDateModule standard datepicker should open datepicker if opened input is set to true": {
625-
"error": "Error: Expected null not to be null.",
626-
"notes": "Unknown"
627-
},
628-
"MatDatepicker with MatNativeDateModule datepicker inside mat-form-field should pass the form field theme color to the overlay": {
629-
"error": "TypeError: Cannot read property 'classList' of null",
630-
"notes": "Unknown"
631-
},
632-
"MatDatepicker with MatNativeDateModule datepicker inside mat-form-field should prefer the datepicker color over the form field one": {
633-
"error": "TypeError: Cannot read property 'classList' of null",
634-
"notes": "Unknown"
635-
},
636624
"MatDialog should set the proper animation states": {
637625
"error": "TypeError: Cannot read property 'componentInstance' of null",
638626
"notes": "FW-1059: DebugNode.query should query nodes in the logical tree"
639627
},
640-
"MatDialog dialog content elements inside component dialog should close the dialog when clicking on the close button": {
641-
"error": "Error: Expected 0 to be 1.",
642-
"notes": "FW-1097: Static host classes and styles don't work on root component"
643-
},
644-
"MatDialog dialog content elements inside component dialog should not close if [mat-dialog-close] is applied on a non-button node": {
645-
"error": "Error: Expected 0 to be 1.",
646-
"notes": "FW-1097: Static host classes and styles don't work on root component"
647-
},
648-
"MatDialog dialog content elements inside template portal should close the dialog when clicking on the close button": {
649-
"error": "Error: Expected 0 to be 1.",
650-
"notes": "FW-1097: Static host classes and styles don't work on root component"
651-
},
652-
"MatDialog dialog content elements inside template portal should not close if [mat-dialog-close] is applied on a non-button node": {
653-
"error": "Error: Expected 0 to be 1.",
654-
"notes": "FW-1097: Static host classes and styles don't work on root component"
655-
},
656-
"MatDialog dialog content elements inside template portal should return the [mat-dialog-close] result when clicking the close button": {
657-
"error": "Uncaught TypeError: Cannot read property 'close' of null thrown",
658-
"notes": "FW-1097: Static host classes and styles don't work on root component"
659-
},
660-
"MatDialog dialog content elements inside template portal should set the aria-labelledby attribute to the id of the title": {
661-
"error": "Error: Expected null to be 'mat-dialog-title-12', 'Expected the aria-labelledby to match the title id.'.",
662-
"notes": "FW-1097: Static host classes and styles don't work on root component"
663-
},
664628
"MatMenu should close the menu when using the CloseScrollStrategy": {
665629
"error": "TypeError: Cannot read property 'openMenu' of undefined",
666630
"notes": "Unknown"

0 commit comments

Comments
 (0)