Skip to content

Commit 1c1fe4e

Browse files
MeAkibclydin
authored andcommitted
fix(@schematics/angular): apply viewEncapsulation to generated application components
The `viewEncapsulation` option of the application schematic had no effect. The root component template did not set `encapsulation`, the value was not added to the component schematic defaults, so components generated later used the default encapsulation, and the `defaultEncapsulation` option added to `bootstrapModule` in `main.ts` for NgModule applications is only used by the JIT compiler. Set `encapsulation` on the root component, add `viewEncapsulation` to the component schematic defaults in `angular.json`, and remove the ineffective `defaultEncapsulation` option from `main.ts`. Fixes #34388
1 parent e378707 commit 1c1fe4e

5 files changed

Lines changed: 49 additions & 15 deletions

File tree

‎packages/schematics/angular/application/files/module-files/src/app/app__suffix__.ts.template‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { Component, signal } from '@angular/core';
1+
import { Component, signal<% if (!!viewEncapsulation) { %>, ViewEncapsulation<% } %> } from '@angular/core';
22

3-
@Component({
3+
@Component({<% if (!!viewEncapsulation) { %>
4+
encapsulation: ViewEncapsulation.<%= viewEncapsulation %>,<% } %>
45
selector: '<%= selector %>',
56
standalone: false,<% if (inlineStyle) { %>
67
styles: [],<% } else { %>
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
<% if (!!viewEncapsulation) { %>import { ViewEncapsulation } from '@angular/core';
2-
<% } %>import { platformBrowser } from '@angular/platform-browser';
1+
import { platformBrowser } from '@angular/platform-browser';
32
import { AppModule } from './app/app<%= typeSeparator %>module';
43

5-
platformBrowser().bootstrapModule(AppModule, {
6-
<% if (!!viewEncapsulation) { %> defaultEncapsulation: ViewEncapsulation.<%= viewEncapsulation %><% } %>
7-
})
4+
platformBrowser().bootstrapModule(AppModule)
85
.catch(err => console.error(err));

‎packages/schematics/angular/application/files/standalone-files/src/app/app__suffix__.ts.template‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { Component, signal } from '@angular/core';<% if (routing) { %>
1+
import { Component, signal<% if (!!viewEncapsulation) { %>, ViewEncapsulation<% } %> } from '@angular/core';<% if (routing) { %>
22
import { RouterOutlet } from '@angular/router';<% } %>
33

4-
@Component({
4+
@Component({<% if (!!viewEncapsulation) { %>
5+
encapsulation: ViewEncapsulation.<%= viewEncapsulation %>,<% } %>
56
imports: [<% if (routing) { %>RouterOutlet<% } %>],
67
selector: '<%= selector %>',<% if (inlineStyle) { %>
78
styles: [],<% } else { %>

‎packages/schematics/angular/application/index.ts‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,8 @@ function addAppToWorkspaceFile(options: ApplicationOptions, appDir: string): Rul
206206
options.inlineTemplate ||
207207
options.inlineStyle ||
208208
options.minimal ||
209-
options.style !== Style.Css
209+
options.style !== Style.Css ||
210+
options.viewEncapsulation
210211
) {
211212
const componentSchematicsOptions: JsonObject = {};
212213
if (options.inlineTemplate ?? options.minimal) {
@@ -218,6 +219,9 @@ function addAppToWorkspaceFile(options: ApplicationOptions, appDir: string): Rul
218219
if (options.style && options.style !== Style.Css) {
219220
componentSchematicsOptions.style = options.style;
220221
}
222+
if (options.viewEncapsulation) {
223+
componentSchematicsOptions.viewEncapsulation = options.viewEncapsulation;
224+
}
221225

222226
schematics['@schematics/angular:component'] = componentSchematicsOptions;
223227
}

‎packages/schematics/angular/application/index_spec.ts‎

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,35 @@ describe('Application Schematic', () => {
704704
expect(main).toContain('bootstrapApplication');
705705
});
706706

707+
it(`should set 'encapsulation' in the root component when 'viewEncapsulation' is provided`, async () => {
708+
const options = { ...defaultOptions, viewEncapsulation: ViewEncapsulation.None };
709+
const tree = await schematicRunner.runSchematic('application', options, workspaceTree);
710+
711+
const component = tree.readContent('/projects/foo/src/app/app.ts');
712+
expect(component).toContain(
713+
`import { Component, signal, ViewEncapsulation } from '@angular/core';`,
714+
);
715+
expect(component).toContain('encapsulation: ViewEncapsulation.None');
716+
});
717+
718+
it(`should add 'viewEncapsulation' to the component schematic defaults when provided`, async () => {
719+
const options = { ...defaultOptions, viewEncapsulation: ViewEncapsulation.None };
720+
const tree = await schematicRunner.runSchematic('application', options, workspaceTree);
721+
722+
const { projects } = JSON.parse(tree.readContent('/angular.json'));
723+
expect(projects.foo.schematics['@schematics/angular:component'].viewEncapsulation).toBe('None');
724+
});
725+
726+
it(`should not set 'encapsulation' in the root component by default`, async () => {
727+
const tree = await schematicRunner.runSchematic('application', defaultOptions, workspaceTree);
728+
729+
expect(tree.readContent('/projects/foo/src/app/app.ts')).not.toContain('encapsulation');
730+
const { projects } = JSON.parse(tree.readContent('/angular.json'));
731+
expect(projects.foo.schematics?.['@schematics/angular:component']?.viewEncapsulation).toBe(
732+
undefined,
733+
);
734+
});
735+
707736
describe('standalone=false', () => {
708737
it('should add the provideZoneChangeDetection with event coalescing option by default with zone.js apps', async () => {
709738
const tree = await schematicRunner.runSchematic(
@@ -720,7 +749,7 @@ describe('Application Schematic', () => {
720749
expect(content).toContain('provideZoneChangeDetection({ eventCoalescing: true })');
721750
});
722751

723-
it(`should set 'defaultEncapsulation' in main.ts when 'ViewEncapsulation' is provided`, async () => {
752+
it(`should set 'encapsulation' in the root component when 'viewEncapsulation' is provided`, async () => {
724753
const tree = await schematicRunner.runSchematic(
725754
'application',
726755
{
@@ -731,10 +760,12 @@ describe('Application Schematic', () => {
731760
workspaceTree,
732761
);
733762

734-
const path = '/projects/foo/src/main.ts';
735-
const content = tree.readContent(path);
736-
expect(content).toContain('defaultEncapsulation: ViewEncapsulation.ShadowDom');
737-
expect(content).toContain(`import { ViewEncapsulation } from '@angular/core'`);
763+
const component = tree.readContent('/projects/foo/src/app/app.ts');
764+
expect(component).toContain(
765+
`import { Component, signal, ViewEncapsulation } from '@angular/core';`,
766+
);
767+
expect(component).toContain('encapsulation: ViewEncapsulation.ShadowDom');
768+
expect(tree.readContent('/projects/foo/src/main.ts')).not.toContain('defaultEncapsulation');
738769
});
739770

740771
it('should handle the routing flag', async () => {

0 commit comments

Comments
 (0)