Skip to content

Commit 97e163f

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 596b9ae commit 97e163f

File tree

69 files changed

+204
-228
lines changed

Some content is hidden

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

69 files changed

+204
-228
lines changed

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

Lines changed: 3 additions & 3 deletions
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 { }
Lines changed: 6 additions & 6 deletions
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 %>');
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ import { Component } from '@angular/core';
1414
styles: []<% } else { %>
1515
styleUrl: './app.component.<%= style %>'<% } %>
1616
})
17-
export class AppComponent {
17+
export class App {
1818
title = '<%= name %>';
1919
}
Lines changed: 6 additions & 6 deletions
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 %>');
Lines changed: 3 additions & 3 deletions
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
}
Lines changed: 2 additions & 2 deletions
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/component/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ export default function (options: ComponentOptions): Rule {
5555

5656
options.module = findModuleFromOptions(host, options);
5757

58+
// Schematic templates require a defined type value
59+
options.type ??= '';
60+
5861
const parsedPath = parseName(options.path, options.name);
5962
options.name = parsedPath.name;
6063
options.path = parsedPath.path;

packages/schematics/angular/component/schema.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,7 @@
9393
},
9494
"type": {
9595
"type": "string",
96-
"description": "Append a custom type to the component's filename. For example, if you set the type to `container`, the file will be named `my-component.container.ts`.",
97-
"default": "Component"
96+
"description": "Append a custom type to the component's filename. For example, if you set the type to `container`, the file will be named `my-component.container.ts`."
9897
},
9998
"skipTests": {
10099
"type": "boolean",

tests/legacy-cli/e2e/tests/basic/aot.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ import { ng } from '../../utils/process';
88
export default async function () {
99
await ng('build', '--aot=true', '--configuration=development');
1010
const content = await readFile('dist/test-project/browser/main.js', 'utf-8');
11-
assert.match(content, /AppComponent_Factory/);
11+
assert.match(content, /App_Factory/);
1212
}

0 commit comments

Comments
 (0)