Skip to content

Commit c8d4e75

Browse files
committed
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 20c64ba commit c8d4e75

File tree

97 files changed

+401
-455
lines changed

Some content is hidden

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

97 files changed

+401
-455
lines changed

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

+5-15
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ function addServerRoutes(options: AppShellOptions): Rule {
205205
.filter((node) => node.kind === ts.SyntaxKind.ImportDeclaration)
206206
.sort((a, b) => a.getStart() - b.getStart());
207207
const insertPosition = imports[imports.length - 1].getEnd();
208-
const routeText = `\n\nconst routes: Routes = [ { path: '${APP_SHELL_ROUTE}', component: AppShellComponent }];`;
208+
const routeText = `\n\nconst routes: Routes = [ { path: '${APP_SHELL_ROUTE}', component: AppShell }];`;
209209
recorder.insertRight(insertPosition, routeText);
210210
host.commitUpdate(recorder);
211211
}
@@ -285,20 +285,15 @@ function addStandaloneServerRoute(options: AppShellOptions): Rule {
285285
multi: true,
286286
useValue: [{
287287
path: '${APP_SHELL_ROUTE}',
288-
component: AppShellComponent
288+
component: AppShell
289289
}]
290290
}\n `,
291291
];
292292

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

295295
applyToUpdateRecorder(recorder, [
296-
insertImport(
297-
configSourceFile,
298-
configFilePath,
299-
'AppShellComponent',
300-
'./app-shell/app-shell.component',
301-
),
296+
insertImport(configSourceFile, configFilePath, 'AppShell', './app-shell/app-shell'),
302297
]);
303298
host.commitUpdate(recorder);
304299
};
@@ -338,16 +333,11 @@ function addServerRoutingConfig(options: AppShellOptions, isStandalone: boolean)
338333
}
339334

340335
recorder = host.beginUpdate(configFilePath);
341-
recorder.insertLeft(functionCall.end - 1, `, withAppShell(AppShellComponent)`);
336+
recorder.insertLeft(functionCall.end - 1, `, withAppShell(AppShell)`);
342337

343338
applyToUpdateRecorder(recorder, [
344339
insertImport(configSourceFile, configFilePath, 'withAppShell', '@angular/ssr'),
345-
insertImport(
346-
configSourceFile,
347-
configFilePath,
348-
'AppShellComponent',
349-
'./app-shell/app-shell.component',
350-
),
340+
insertImport(configSourceFile, configFilePath, 'AppShell', './app-shell/app-shell'),
351341
]);
352342

353343
host.commitUpdate(recorder);

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

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

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

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

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

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

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

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

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 { }

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

+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 %>');

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

+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
}

packages/schematics/angular/application/files/standalone-files/src/app/app.component.spec.ts.template packages/schematics/angular/application/files/standalone-files/src/app/app.spec.ts.template

+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 %>');

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

+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
@@ -56,10 +56,10 @@ describe('Application Schematic', () => {
5656
'/projects/foo/src/main.ts',
5757
'/projects/foo/src/styles.css',
5858
'/projects/foo/src/app/app.module.ts',
59-
'/projects/foo/src/app/app.component.css',
60-
'/projects/foo/src/app/app.component.ng.html',
61-
'/projects/foo/src/app/app.component.spec.ts',
62-
'/projects/foo/src/app/app.component.ts',
59+
'/projects/foo/src/app/app.css',
60+
'/projects/foo/src/app/app.ng.html',
61+
'/projects/foo/src/app/app.spec.ts',
62+
'/projects/foo/src/app/app.ts',
6363
]),
6464
);
6565
});
@@ -266,10 +266,10 @@ describe('Application Schematic', () => {
266266
'/src/index.html',
267267
'/src/main.ts',
268268
'/src/styles.css',
269-
'/src/app/app.component.css',
270-
'/src/app/app.component.ng.html',
271-
'/src/app/app.component.spec.ts',
272-
'/src/app/app.component.ts',
269+
'/src/app/app.css',
270+
'/src/app/app.ng.html',
271+
'/src/app/app.spec.ts',
272+
'/src/app/app.ts',
273273
]),
274274
);
275275
});
@@ -447,9 +447,9 @@ describe('Application Schematic', () => {
447447
const files = tree.files;
448448
[
449449
'/projects/foo/tsconfig.spec.json',
450-
'/projects/foo/src/app/app.component.css',
451-
'/projects/foo/src/app/app.component.ng.html',
452-
'/projects/foo/src/app/app.component.spec.ts',
450+
'/projects/foo/src/app/app.css',
451+
'/projects/foo/src/app/app.ng.html',
452+
'/projects/foo/src/app/app.spec.ts',
453453
].forEach((x) => expect(files).not.toContain(x));
454454

455455
expect(files).toEqual(
@@ -459,7 +459,7 @@ describe('Application Schematic', () => {
459459
'/projects/foo/src/index.html',
460460
'/projects/foo/src/main.ts',
461461
'/projects/foo/src/styles.css',
462-
'/projects/foo/src/app/app.component.ts',
462+
'/projects/foo/src/app/app.ts',
463463
]),
464464
);
465465
});
@@ -473,8 +473,8 @@ describe('Application Schematic', () => {
473473
'/projects/foo/tsconfig.spec.json',
474474
'/projects/foo/karma.conf.js',
475475
'/projects/foo/src/test.ts',
476-
'/projects/foo/src/app/app.component.ng.html',
477-
'/projects/foo/src/app/app.component.spec.ts',
476+
'/projects/foo/src/app/app.ng.html',
477+
'/projects/foo/src/app/app.spec.ts',
478478
].forEach((x) => expect(files).not.toContain(x));
479479

480480
expect(files).toEqual(
@@ -484,8 +484,8 @@ describe('Application Schematic', () => {
484484
'/projects/foo/src/index.html',
485485
'/projects/foo/src/main.ts',
486486
'/projects/foo/src/styles.css',
487-
'/projects/foo/src/app/app.component.css',
488-
'/projects/foo/src/app/app.component.ts',
487+
'/projects/foo/src/app/app.css',
488+
'/projects/foo/src/app/app.ts',
489489
]),
490490
);
491491
});
@@ -499,8 +499,8 @@ describe('Application Schematic', () => {
499499
'/projects/foo/tsconfig.spec.json',
500500
'/projects/foo/karma.conf.js',
501501
'/projects/foo/src/test.ts',
502-
'/projects/foo/src/app/app.component.css',
503-
'/projects/foo/src/app/app.component.spec.ts',
502+
'/projects/foo/src/app/app.css',
503+
'/projects/foo/src/app/app.spec.ts',
504504
].forEach((x) => expect(files).not.toContain(x));
505505

506506
expect(files).toEqual(
@@ -510,8 +510,8 @@ describe('Application Schematic', () => {
510510
'/projects/foo/src/index.html',
511511
'/projects/foo/src/main.ts',
512512
'/projects/foo/src/styles.css',
513-
'/projects/foo/src/app/app.component.ng.html',
514-
'/projects/foo/src/app/app.component.ts',
513+
'/projects/foo/src/app/app.ng.html',
514+
'/projects/foo/src/app/app.ts',
515515
]),
516516
);
517517
});
@@ -531,10 +531,10 @@ describe('Application Schematic', () => {
531531
'/projects/foo/src/main.ts',
532532
'/projects/foo/src/styles.css',
533533
'/projects/foo/src/app/app.config.ts',
534-
'/projects/foo/src/app/app.component.css',
535-
'/projects/foo/src/app/app.component.ng.html',
536-
'/projects/foo/src/app/app.component.spec.ts',
537-
'/projects/foo/src/app/app.component.ts',
534+
'/projects/foo/src/app/app.css',
535+
'/projects/foo/src/app/app.ng.html',
536+
'/projects/foo/src/app/app.spec.ts',
537+
'/projects/foo/src/app/app.ts',
538538
]),
539539
);
540540
});
@@ -558,7 +558,7 @@ describe('Application Schematic', () => {
558558
it('should create a standalone component', async () => {
559559
const options = { ...defaultOptions, standalone: true };
560560
const tree = await schematicRunner.runSchematic('application', options, workspaceTree);
561-
const component = tree.readContent('/projects/foo/src/app/app.component.ts');
561+
const component = tree.readContent('/projects/foo/src/app/app.ts');
562562

563563
expect(component).not.toContain('standalone');
564564
});
@@ -570,7 +570,7 @@ describe('Application Schematic', () => {
570570

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

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

@@ -655,7 +655,7 @@ describe('Application Schematic', () => {
655655

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

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

0 commit comments

Comments
 (0)