From c76ae06664550eaacf82a85a67b542218012c610 Mon Sep 17 00:00:00 2001 From: Chintan Kavathia Date: Wed, 4 Sep 2024 12:46:29 +0530 Subject: [PATCH] fix(core): preserve static class/styles on root component Fix to preserve statically applied classes and styles on root component while using host binding. Fixes #51460 --- .../core/src/render3/node_manipulation.ts | 16 ++++++++++-- .../core/test/acceptance/bootstrap_spec.ts | 26 +++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/packages/core/src/render3/node_manipulation.ts b/packages/core/src/render3/node_manipulation.ts index 952144b58f221e..fd067a4f028774 100644 --- a/packages/core/src/render3/node_manipulation.ts +++ b/packages/core/src/render3/node_manipulation.ts @@ -1280,10 +1280,22 @@ export function setupStaticAttributes(renderer: Renderer, element: RElement, tNo } if (classes !== null) { - writeDirectClass(renderer, element, classes); + const elementClasses = element.className.split + ? (element.className + .split(' ') + .filter((item) => !classes.includes(item)) + .join(' ') ?? '') + : ''; + writeDirectClass(renderer, element, `${classes} ${elementClasses}`.trim()); } if (styles !== null) { - writeDirectStyle(renderer, element, styles); + const elementStyles = + element + .getAttribute('style') + ?.split(';') + .filter((item) => !styles.includes(item)) + .join(';') ?? ''; + writeDirectStyle(renderer, element, `${styles} ${elementStyles}`.trim()); } } diff --git a/packages/core/test/acceptance/bootstrap_spec.ts b/packages/core/test/acceptance/bootstrap_spec.ts index 004f5f9ae66c9d..a66372f16afa0f 100644 --- a/packages/core/test/acceptance/bootstrap_spec.ts +++ b/packages/core/test/acceptance/bootstrap_spec.ts @@ -21,6 +21,7 @@ import { ViewEncapsulation, ɵNoopNgZone, ɵZONELESS_ENABLED, + ElementRef, } from '@angular/core'; import {bootstrapApplication, BrowserModule} from '@angular/platform-browser'; import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; @@ -82,6 +83,31 @@ describe('bootstrap', () => { }), ); + it( + 'should preserve static class and styles on root component', + withBody('', async () => { + @Component({ + selector: 'test-cmp', + standalone: true, + template: '(test)', + host: { + class: 'baar', + style: 'width: 100%;', + }, + }) + class TestCmp { + constructor(public element: ElementRef) {} + } + const appRef = await bootstrapApplication(TestCmp); + expect(appRef.components[0].instance.element.nativeElement.className).toBe('baar foo'); + expect(appRef.components[0].instance.element.nativeElement.getAttribute('style')).toBe( + 'width: 100%; height: 100%', + ); + + appRef.destroy(); + }), + ); + describe('options', () => { function createComponentAndModule( options: {