Skip to content

Commit 23fc8e1

Browse files
clydindgp1130
authored andcommitted
fix(@schematics/angular): generate components without a .component extension/type
To align with the updated style guide, Angular v20 will generate components without a `.component` file extension type for all component related files by default. Projects will automatically use this naming convention. Projects can however opt-out by setting the `type` option to `Component` for the component schematic. This can be done as a default in the `angular.json` or directly on the commandline via `--type=Component` when executing `ng generate`. As an example, `app.component.css` will now be named `app.css`. Additionally, the TypeScript class name will be `App` instead of the previous `AppComponent`.
1 parent f126f8d commit 23fc8e1

File tree

94 files changed

+399
-453
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+399
-453
lines changed

packages/schematics/angular/app-shell/index.ts

+5-15
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ function addServerRoutes(options: AppShellOptions): Rule {
182182
.filter((node) => node.kind === ts.SyntaxKind.ImportDeclaration)
183183
.sort((a, b) => a.getStart() - b.getStart());
184184
const insertPosition = imports[imports.length - 1].getEnd();
185-
const routeText = `\n\nconst routes: Routes = [ { path: '${APP_SHELL_ROUTE}', component: AppShellComponent }];`;
185+
const routeText = `\n\nconst routes: Routes = [ { path: '${APP_SHELL_ROUTE}', component: AppShell }];`;
186186
recorder.insertRight(insertPosition, routeText);
187187
host.commitUpdate(recorder);
188188
}
@@ -262,20 +262,15 @@ function addStandaloneServerRoute(options: AppShellOptions): Rule {
262262
multi: true,
263263
useValue: [{
264264
path: '${APP_SHELL_ROUTE}',
265-
component: AppShellComponent
265+
component: AppShell
266266
}]
267267
}\n `,
268268
];
269269

270270
recorder.insertRight(providersLiteral.getStart(), `[\n${updatedProvidersString.join(',\n')}]`);
271271

272272
applyToUpdateRecorder(recorder, [
273-
insertImport(
274-
configSourceFile,
275-
configFilePath,
276-
'AppShellComponent',
277-
'./app-shell/app-shell.component',
278-
),
273+
insertImport(configSourceFile, configFilePath, 'AppShell', './app-shell/app-shell'),
279274
]);
280275
host.commitUpdate(recorder);
281276
};
@@ -315,16 +310,11 @@ function addServerRoutingConfig(options: AppShellOptions, isStandalone: boolean)
315310
}
316311

317312
recorder = host.beginUpdate(configFilePath);
318-
recorder.insertLeft(functionCall.end - 1, `, withAppShell(AppShellComponent)`);
313+
recorder.insertLeft(functionCall.end - 1, `, withAppShell(AppShell)`);
319314

320315
applyToUpdateRecorder(recorder, [
321316
insertImport(configSourceFile, configFilePath, 'withAppShell', '@angular/ssr'),
322-
insertImport(
323-
configSourceFile,
324-
configFilePath,
325-
'AppShellComponent',
326-
'./app-shell/app-shell.component',
327-
),
317+
insertImport(configSourceFile, configFilePath, 'AppShell', './app-shell/app-shell'),
328318
]);
329319

330320
host.commitUpdate(recorder);

packages/schematics/angular/app-shell/index_spec.ts

+8-10
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,14 @@ describe('App Shell Schematic', () => {
8282
it('should work if server config was added prior to running the app-shell schematic', async () => {
8383
let tree = await schematicRunner.runSchematic('server', defaultOptions, appTree);
8484
tree = await schematicRunner.runSchematic('app-shell', defaultOptions, tree);
85-
expect(tree.exists('/projects/bar/src/app/app-shell/app-shell.component.ts')).toBe(true);
85+
expect(tree.exists('/projects/bar/src/app/app-shell/app-shell.ts')).toBe(true);
8686
});
8787

8888
it('should create the shell component', async () => {
8989
const tree = await schematicRunner.runSchematic('app-shell', defaultOptions, appTree);
90-
expect(tree.exists('/projects/bar/src/app/app-shell/app-shell.component.ts')).toBe(true);
90+
expect(tree.exists('/projects/bar/src/app/app-shell/app-shell.ts')).toBe(true);
9191
const content = tree.readContent('/projects/bar/src/app/app.module.server.ts');
92-
expect(content).toMatch(/app-shell\.component/);
92+
expect(content).toMatch(/app-shell/);
9393
});
9494
});
9595

@@ -117,27 +117,25 @@ describe('App Shell Schematic', () => {
117117

118118
it('should create the shell component', async () => {
119119
const tree = await schematicRunner.runSchematic('app-shell', defaultOptions, appTree);
120-
expect(tree.exists('/projects/bar/src/app/app-shell/app-shell.component.ts')).toBe(true);
120+
expect(tree.exists('/projects/bar/src/app/app-shell/app-shell.ts')).toBe(true);
121121
const content = tree.readContent('/projects/bar/src/app/app.config.server.ts');
122122

123-
expect(content).toMatch(/app-shell\.component/);
123+
expect(content).toMatch(/app-shell/);
124124
});
125125

126126
it(`should update the 'provideServerRouting' call to include 'withAppShell'`, async () => {
127127
const tree = await schematicRunner.runSchematic('app-shell', defaultOptions, appTree);
128128
const content = tree.readContent('/projects/bar/src/app/app.config.server.ts');
129129
expect(tags.oneLine`${content}`).toContain(
130-
tags.oneLine`provideServerRouting(serverRoutes, withAppShell(AppShellComponent))`,
130+
tags.oneLine`provideServerRouting(serverRoutes, withAppShell(AppShell))`,
131131
);
132132
});
133133

134-
it(`should add import to 'AppShellComponent'`, async () => {
134+
it(`should add import to 'AppShell'`, async () => {
135135
const tree = await schematicRunner.runSchematic('app-shell', defaultOptions, appTree);
136136
const filePath = '/projects/bar/src/app/app.config.server.ts';
137137
const content = tree.readContent(filePath);
138-
expect(content).toContain(
139-
`import { AppShellComponent } from './app-shell/app-shell.component';`,
140-
);
138+
expect(content).toContain(`import { AppShell } from './app-shell/app-shell';`);
141139
});
142140
});
143141
});

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@ import { NgModule<% if(experimentalZoneless) { %>, provideExperimentalZonelessCh
22
import { BrowserModule } from '@angular/platform-browser';
33
<% if (routing) { %>
44
import { AppRoutingModule } from './app-routing.module';<% } %>
5-
import { AppComponent } from './app.component';
5+
import { App } from './app';
66

77
@NgModule({
88
declarations: [
9-
AppComponent
9+
App
1010
],
1111
imports: [
1212
BrowserModule<% if (routing) { %>,
1313
AppRoutingModule<% } %>
1414
],
1515
providers: [<% if (experimentalZoneless) { %>provideExperimentalZonelessChangeDetection()<% } %>],
16-
bootstrap: [AppComponent]
16+
bootstrap: [App]
1717
})
1818
export class AppModule { }
+6-6
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,35 @@
11
<% if(experimentalZoneless) { %>import { provideExperimentalZonelessChangeDetection } from '@angular/core';
22
<% } %>import { TestBed } from '@angular/core/testing';<% if (routing) { %>
33
import { RouterModule } from '@angular/router';<% } %>
4-
import { AppComponent } from './app.component';
4+
import { App } from './app';
55

6-
describe('AppComponent', () => {
6+
describe('App', () => {
77
beforeEach(async () => {
88
await TestBed.configureTestingModule({<% if (routing) { %>
99
imports: [
1010
RouterModule.forRoot([])
1111
],<% } %>
1212
declarations: [
13-
AppComponent
13+
App
1414
],<% if(experimentalZoneless) { %>
1515
providers: [provideExperimentalZonelessChangeDetection()]<% } %>
1616
}).compileComponents();
1717
});
1818

1919
it('should create the app', () => {
20-
const fixture = TestBed.createComponent(AppComponent);
20+
const fixture = TestBed.createComponent(App);
2121
const app = fixture.componentInstance;
2222
expect(app).toBeTruthy();
2323
});
2424

2525
it(`should have as title '<%= name %>'`, () => {
26-
const fixture = TestBed.createComponent(AppComponent);
26+
const fixture = TestBed.createComponent(App);
2727
const app = fixture.componentInstance;
2828
expect(app.title).toEqual('<%= name %>');
2929
});
3030

3131
it('should render title', () => {
32-
const fixture = TestBed.createComponent(AppComponent);
32+
const fixture = TestBed.createComponent(App);
3333
fixture.detectChanges();
3434
const compiled = fixture.nativeElement as HTMLElement;
3535
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, <%= name %>');
+3-3
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ import { Component } from '@angular/core';
99
%><router-outlet /><%
1010
} %>
1111
`,<% } else { %>
12-
templateUrl: './app.component.ng.html',<% } %>
12+
templateUrl: './app.ng.html',<% } %>
1313
standalone: false,<% if(inlineStyle) { %>
1414
styles: []<% } else { %>
15-
styleUrl: './app.component.<%= style %>'<% } %>
15+
styleUrl: './app.<%= style %>'<% } %>
1616
})
17-
export class AppComponent {
17+
export class App {
1818
title = '<%= name %>';
1919
}
+6-6
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
<% if(experimentalZoneless) { %>import { provideExperimentalZonelessChangeDetection } from '@angular/core';
22
<% } %>import { TestBed } from '@angular/core/testing';
3-
import { AppComponent } from './app.component';
3+
import { App } from './app';
44

5-
describe('AppComponent', () => {
5+
describe('App', () => {
66
beforeEach(async () => {
77
await TestBed.configureTestingModule({
8-
imports: [AppComponent],<% if(experimentalZoneless) { %>
8+
imports: [App],<% if(experimentalZoneless) { %>
99
providers: [provideExperimentalZonelessChangeDetection()]<% } %>
1010
}).compileComponents();
1111
});
1212

1313
it('should create the app', () => {
14-
const fixture = TestBed.createComponent(AppComponent);
14+
const fixture = TestBed.createComponent(App);
1515
const app = fixture.componentInstance;
1616
expect(app).toBeTruthy();
1717
});
1818

1919
it(`should have the '<%= name %>' title`, () => {
20-
const fixture = TestBed.createComponent(AppComponent);
20+
const fixture = TestBed.createComponent(App);
2121
const app = fixture.componentInstance;
2222
expect(app.title).toEqual('<%= name %>');
2323
});
2424

2525
it('should render title', () => {
26-
const fixture = TestBed.createComponent(AppComponent);
26+
const fixture = TestBed.createComponent(App);
2727
fixture.detectChanges();
2828
const compiled = fixture.nativeElement as HTMLElement;
2929
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, <%= name %>');
+3-3
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ import { RouterOutlet } from '@angular/router';<% } %>
1111
%><router-outlet /><%
1212
} %>
1313
`,<% } else { %>
14-
templateUrl: './app.component.ng.html',<% } if(inlineStyle) { %>
14+
templateUrl: './app.ng.html',<% } if(inlineStyle) { %>
1515
styles: [],<% } else { %>
16-
styleUrl: './app.component.<%= style %>'<% } %>
16+
styleUrl: './app.<%= style %>'<% } %>
1717
})
18-
export class AppComponent {
18+
export class App {
1919
title = '<%= name %>';
2020
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { bootstrapApplication } from '@angular/platform-browser';
22
import { appConfig } from './app/app.config';
3-
import { AppComponent } from './app/app.component';
3+
import { App } from './app/app';
44

5-
bootstrapApplication(AppComponent, appConfig)
5+
bootstrapApplication(App, appConfig)
66
.catch((err) => console.error(err));

packages/schematics/angular/application/index_spec.ts

+31-31
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@ describe('Application Schematic', () => {
5555
'/projects/foo/src/main.ts',
5656
'/projects/foo/src/styles.css',
5757
'/projects/foo/src/app/app.module.ts',
58-
'/projects/foo/src/app/app.component.css',
59-
'/projects/foo/src/app/app.component.ng.html',
60-
'/projects/foo/src/app/app.component.spec.ts',
61-
'/projects/foo/src/app/app.component.ts',
58+
'/projects/foo/src/app/app.css',
59+
'/projects/foo/src/app/app.ng.html',
60+
'/projects/foo/src/app/app.spec.ts',
61+
'/projects/foo/src/app/app.ts',
6262
]),
6363
);
6464
});
@@ -265,10 +265,10 @@ describe('Application Schematic', () => {
265265
'/src/index.html',
266266
'/src/main.ts',
267267
'/src/styles.css',
268-
'/src/app/app.component.css',
269-
'/src/app/app.component.ng.html',
270-
'/src/app/app.component.spec.ts',
271-
'/src/app/app.component.ts',
268+
'/src/app/app.css',
269+
'/src/app/app.ng.html',
270+
'/src/app/app.spec.ts',
271+
'/src/app/app.ts',
272272
]),
273273
);
274274
});
@@ -446,9 +446,9 @@ describe('Application Schematic', () => {
446446
const files = tree.files;
447447
[
448448
'/projects/foo/tsconfig.spec.json',
449-
'/projects/foo/src/app/app.component.css',
450-
'/projects/foo/src/app/app.component.ng.html',
451-
'/projects/foo/src/app/app.component.spec.ts',
449+
'/projects/foo/src/app/app.css',
450+
'/projects/foo/src/app/app.ng.html',
451+
'/projects/foo/src/app/app.spec.ts',
452452
].forEach((x) => expect(files).not.toContain(x));
453453

454454
expect(files).toEqual(
@@ -458,7 +458,7 @@ describe('Application Schematic', () => {
458458
'/projects/foo/src/index.html',
459459
'/projects/foo/src/main.ts',
460460
'/projects/foo/src/styles.css',
461-
'/projects/foo/src/app/app.component.ts',
461+
'/projects/foo/src/app/app.ts',
462462
]),
463463
);
464464
});
@@ -472,8 +472,8 @@ describe('Application Schematic', () => {
472472
'/projects/foo/tsconfig.spec.json',
473473
'/projects/foo/karma.conf.js',
474474
'/projects/foo/src/test.ts',
475-
'/projects/foo/src/app/app.component.ng.html',
476-
'/projects/foo/src/app/app.component.spec.ts',
475+
'/projects/foo/src/app/app.ng.html',
476+
'/projects/foo/src/app/app.spec.ts',
477477
].forEach((x) => expect(files).not.toContain(x));
478478

479479
expect(files).toEqual(
@@ -483,8 +483,8 @@ describe('Application Schematic', () => {
483483
'/projects/foo/src/index.html',
484484
'/projects/foo/src/main.ts',
485485
'/projects/foo/src/styles.css',
486-
'/projects/foo/src/app/app.component.css',
487-
'/projects/foo/src/app/app.component.ts',
486+
'/projects/foo/src/app/app.css',
487+
'/projects/foo/src/app/app.ts',
488488
]),
489489
);
490490
});
@@ -498,8 +498,8 @@ describe('Application Schematic', () => {
498498
'/projects/foo/tsconfig.spec.json',
499499
'/projects/foo/karma.conf.js',
500500
'/projects/foo/src/test.ts',
501-
'/projects/foo/src/app/app.component.css',
502-
'/projects/foo/src/app/app.component.spec.ts',
501+
'/projects/foo/src/app/app.css',
502+
'/projects/foo/src/app/app.spec.ts',
503503
].forEach((x) => expect(files).not.toContain(x));
504504

505505
expect(files).toEqual(
@@ -509,8 +509,8 @@ describe('Application Schematic', () => {
509509
'/projects/foo/src/index.html',
510510
'/projects/foo/src/main.ts',
511511
'/projects/foo/src/styles.css',
512-
'/projects/foo/src/app/app.component.ng.html',
513-
'/projects/foo/src/app/app.component.ts',
512+
'/projects/foo/src/app/app.ng.html',
513+
'/projects/foo/src/app/app.ts',
514514
]),
515515
);
516516
});
@@ -530,10 +530,10 @@ describe('Application Schematic', () => {
530530
'/projects/foo/src/main.ts',
531531
'/projects/foo/src/styles.css',
532532
'/projects/foo/src/app/app.config.ts',
533-
'/projects/foo/src/app/app.component.css',
534-
'/projects/foo/src/app/app.component.ng.html',
535-
'/projects/foo/src/app/app.component.spec.ts',
536-
'/projects/foo/src/app/app.component.ts',
533+
'/projects/foo/src/app/app.css',
534+
'/projects/foo/src/app/app.ng.html',
535+
'/projects/foo/src/app/app.spec.ts',
536+
'/projects/foo/src/app/app.ts',
537537
]),
538538
);
539539
});
@@ -557,7 +557,7 @@ describe('Application Schematic', () => {
557557
it('should create a standalone component', async () => {
558558
const options = { ...defaultOptions, standalone: true };
559559
const tree = await schematicRunner.runSchematic('application', options, workspaceTree);
560-
const component = tree.readContent('/projects/foo/src/app/app.component.ts');
560+
const component = tree.readContent('/projects/foo/src/app/app.ts');
561561

562562
expect(component).not.toContain('standalone');
563563
});
@@ -569,7 +569,7 @@ describe('Application Schematic', () => {
569569

570570
expect(tree.files).toContain('/projects/foo/src/app/app.routes.ts');
571571

572-
const component = tree.readContent('/projects/foo/src/app/app.component.ts');
572+
const component = tree.readContent('/projects/foo/src/app/app.ts');
573573
expect(component).toContain(`import { RouterOutlet } from '@angular/router';`);
574574
expect(component).toContain(`imports: [RouterOutlet]`);
575575

@@ -654,7 +654,7 @@ describe('Application Schematic', () => {
654654

655655
const path = '/projects/foo/src/app/app.module.ts';
656656
const content = tree.readContent(path);
657-
expect(content).toMatch(/import { AppComponent } from '\.\/app\.component';/);
657+
expect(content).toMatch(/import { App } from '\.\/app';/);
658658
});
659659

660660
it('should create all files of an application', async () => {
@@ -671,10 +671,10 @@ describe('Application Schematic', () => {
671671
'/projects/foo/src/styles.css',
672672
'/projects/foo/src/app/app-routing.module.ts',
673673
'/projects/foo/src/app/app.module.ts',
674-
'/projects/foo/src/app/app.component.css',
675-
'/projects/foo/src/app/app.component.ng.html',
676-
'/projects/foo/src/app/app.component.spec.ts',
677-
'/projects/foo/src/app/app.component.ts',
674+
'/projects/foo/src/app/app.css',
675+
'/projects/foo/src/app/app.ng.html',
676+
'/projects/foo/src/app/app.spec.ts',
677+
'/projects/foo/src/app/app.ts',
678678
]),
679679
);
680680
});

0 commit comments

Comments
 (0)