Skip to content

Commit 0d70f41

Browse files
committed
feat(angular): generate components without a .component/Component suffix/type
1 parent 23f35e6 commit 0d70f41

File tree

94 files changed

+2485
-1518
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

+2485
-1518
lines changed

docs/generated/packages/angular/generators/component.json

+2-3
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,7 @@
9595
},
9696
"type": {
9797
"type": "string",
98-
"description": "Adds a developer-defined type to the filename, in the format `name.type.ts`.",
99-
"default": "component"
98+
"description": "Append a custom type to the component's filename. It defaults to 'component' for Angular versions below v20. For Angular v20 and above, no type is appended unless specified."
10099
},
101100
"export": {
102101
"type": "boolean",
@@ -122,7 +121,7 @@
122121
}
123122
},
124123
"required": ["path"],
125-
"examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Simple Component\" %}\n\nGenerate a component named `MyComponent` at `apps/my-app/src/lib/my-component/my-component.component.ts`:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/my-component/my-component.ts\n```\n\n{% /tab %}\n\n{% tab label=\"Without Providing the File Extension\" %}\n\nGenerate a component named `MyComponent` at `apps/my-app/src/lib/my-component/my-component.component.ts`:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/my-component/my-component\n```\n\n{% /tab %}\n\n{% tab label=\"With Different Symbol Name\" %}\n\nGenerate a component named `CustomComponent` at `apps/my-app/src/lib/my-component/my-component.component.ts`:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/my-component/my-component --name=custom\n```\n\n{% /tab %}\n\n{% tab label=\"Single File Component\" %}\n\nCreate a component named `my-component` with inline styles and inline template:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/my-component/my-component --inlineStyle --inlineTemplate\n```\n\n{% /tab %}\n\n{% tab label=\"Component with OnPush Change Detection Strategy\" %}\n\nCreate a component named `my-component` with OnPush Change Detection Strategy:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/my-component/my-component --changeDetection=OnPush\n```\n\n{% /tab %}\n",
124+
"examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Simple Component\" %}\n\nGenerate a component named `Card` at `apps/my-app/src/lib/card/card.ts`:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/card/card.ts\n```\n\n{% /tab %}\n\n{% tab label=\"Without Providing the File Extension\" %}\n\nGenerate a component named `Card` at `apps/my-app/src/lib/card/card.ts`:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/card/card\n```\n\n{% /tab %}\n\n{% tab label=\"With Different Symbol Name\" %}\n\nGenerate a component named `Custom` at `apps/my-app/src/lib/card/card.ts`:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/card/card --name=custom\n```\n\n{% /tab %}\n\n{% tab label=\"With a Component Type\" %}\n\nGenerate a component named `CardComponent` at `apps/my-app/src/lib/card/card.component.ts`:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/card/card --type=component\n```\n\n{% /tab %}\n\n{% tab label=\"Single File Component\" %}\n\nCreate a component named `Card` with inline styles and inline template:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/card/card --inlineStyle --inlineTemplate\n```\n\n{% /tab %}\n\n{% tab label=\"Component with OnPush Change Detection Strategy\" %}\n\nCreate a component named `Card` with `OnPush` Change Detection Strategy:\n\n```bash\nnx g @nx/angular:component apps/my-app/src/lib/card/card --changeDetection=OnPush\n```\n\n{% /tab %}\n",
126125
"presets": []
127126
},
128127
"aliases": ["c"],

docs/generated/packages/angular/generators/scam.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,7 @@
9494
},
9595
"type": {
9696
"type": "string",
97-
"description": "Adds a developer-defined type to the filename, in the format `name.type.ts`.",
98-
"default": "component"
97+
"description": "Append a custom type to the component's filename. It defaults to 'component' for Angular versions below v20. For Angular v20 and above, no type is appended unless specified."
9998
},
10099
"prefix": {
101100
"type": "string",

e2e/angular/src/cypress-component-tests.test.ts

+25-25
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ describe('Angular Cypress Component Tests', () => {
8888
}
8989
);
9090
updateFile(
91-
`${buildableLibName}/src/lib/input-standalone/input-standalone.component.cy.ts`,
91+
`${buildableLibName}/src/lib/input-standalone/input-standalone.cy.ts`,
9292
(content) => {
9393
// text-green-500 should now apply
9494
return content.replace('rgb(0, 0, 0)', 'rgb(34, 197, 94)');
@@ -149,7 +149,7 @@ function createLib(projectName: string, appName: string, libName: string) {
149149
`generate @nx/angular:component ${libName}/src/lib/btn-standalone/btn-standalone --inlineTemplate --inlineStyle --export --standalone --no-interactive`
150150
);
151151
updateFile(
152-
`${libName}/src/lib/btn/btn.component.ts`,
152+
`${libName}/src/lib/btn/btn.ts`,
153153
`
154154
import { Component, Input } from '@angular/core';
155155
@@ -158,13 +158,13 @@ import { Component, Input } from '@angular/core';
158158
template: '<button class="text-green-500">{{text}}</button>',
159159
styles: []
160160
})
161-
export class BtnComponent {
161+
export class Btn {
162162
@Input() text = 'something';
163163
}
164164
`
165165
);
166166
updateFile(
167-
`${libName}/src/lib/btn-standalone/btn-standalone.component.ts`,
167+
`${libName}/src/lib/btn-standalone/btn-standalone.ts`,
168168
`
169169
import { Component, Input } from '@angular/core';
170170
import { CommonModule } from '@angular/common';
@@ -175,7 +175,7 @@ import { CommonModule } from '@angular/common';
175175
template: '<button class="text-green-500">standlone-{{text}}</button>',
176176
styles: [],
177177
})
178-
export class BtnStandaloneComponent {
178+
export class BtnStandalone {
179179
@Input() text = 'something';
180180
}
181181
`
@@ -187,7 +187,7 @@ function createBuildableLib(projectName: string, libName: string) {
187187
runCLI(`generate @nx/angular:lib ${libName} --buildable --no-interactive`);
188188
// create cmp for lib
189189
runCLI(
190-
`generate @nx/angular:component ${libName}/src/lib/input/input --inlineTemplate --inlineStyle --export --no-interactive`
190+
`generate @nx/angular:component ${libName}/src/lib/input/input.component --inlineTemplate --inlineStyle --export --no-interactive`
191191
);
192192
// create standlone cmp for lib
193193
runCLI(
@@ -210,7 +210,7 @@ import {Component, Input} from '@angular/core';
210210
`
211211
);
212212
updateFile(
213-
`${libName}/src/lib/input-standalone/input-standalone.component.ts`,
213+
`${libName}/src/lib/input-standalone/input-standalone.ts`,
214214
`
215215
import {Component, Input} from '@angular/core';
216216
import {CommonModule} from '@angular/common';
@@ -221,7 +221,7 @@ import {CommonModule} from '@angular/common';
221221
template: \`<label class="text-green-500">Email: <input class="border-blue-500" type="email" [readOnly]="readOnly"></label>\`,
222222
styles : []
223223
})
224-
export class InputStandaloneComponent{
224+
export class InputStandalone{
225225
@Input() readOnly = false;
226226
}
227227
`
@@ -230,7 +230,7 @@ import {CommonModule} from '@angular/common';
230230

231231
function useLibInApp(projectName: string, appName: string, libName: string) {
232232
createFile(
233-
`${appName}/src/app/app.component.html`,
233+
`${appName}/src/app/app.html`,
234234
`
235235
<${projectName}-btn></${projectName}-btn>
236236
<${projectName}-btn-standalone></${projectName}-btn-standalone>
@@ -239,7 +239,7 @@ function useLibInApp(projectName: string, appName: string, libName: string) {
239239
);
240240
const btnModuleName = names(libName).className;
241241
updateFile(
242-
`${appName}/src/app/app.component.scss`,
242+
`${appName}/src/app/app.scss`,
243243
`
244244
@use 'styleguide' as *;
245245
@@ -254,14 +254,14 @@ import { NgModule } from '@angular/core';
254254
import { BrowserModule } from '@angular/platform-browser';
255255
import {${btnModuleName}Module} from "@${projectName}/${libName}";
256256
257-
import { AppComponent } from './app.component';
258-
import { NxWelcomeComponent } from './nx-welcome.component';
257+
import { App } from './app';
258+
import { NxWelcome } from './nx-welcome';
259259
260260
@NgModule({
261-
declarations: [AppComponent, NxWelcomeComponent],
261+
declarations: [App, NxWelcome],
262262
imports: [BrowserModule, ${btnModuleName}Module],
263263
providers: [],
264-
bootstrap: [AppComponent],
264+
bootstrap: [App],
265265
})
266266
export class AppModule {}
267267
`
@@ -328,25 +328,25 @@ describe(InputComponent.name, () => {
328328
);
329329

330330
createFile(
331-
`${libName}/src/lib/input-standalone/input-standalone.component.cy.ts`,
331+
`${libName}/src/lib/input-standalone/input-standalone.cy.ts`,
332332
`
333333
import { MountConfig } from 'cypress/angular';
334-
import { InputStandaloneComponent } from './input-standalone.component';
334+
import { InputStandalone } from './input-standalone';
335335
336-
describe(InputStandaloneComponent.name, () => {
337-
const config: MountConfig<InputStandaloneComponent> = {
336+
describe(InputStandalone.name, () => {
337+
const config: MountConfig<InputStandalone> = {
338338
declarations: [],
339339
imports: [],
340340
providers: [],
341341
};
342342
343343
it('renders', () => {
344-
cy.mount(InputStandaloneComponent, config);
344+
cy.mount(InputStandalone, config);
345345
// make sure tailwind isn't getting applied
346346
cy.get('label').should('have.css', 'color', 'rgb(0, 0, 0)');
347347
});
348348
it('should be readonly', () => {
349-
cy.mount(InputStandaloneComponent, {
349+
cy.mount(InputStandalone, {
350350
...config,
351351
componentProperties: {
352352
readOnly: true,
@@ -367,19 +367,19 @@ function useBuildableLibInLib(
367367
const buildLibNames = names(buildableLibName);
368368
// use the buildable lib in lib so now buildableLib has an indirect dep on app
369369
updateFile(
370-
`${libName}/src/lib/btn-standalone/btn-standalone.component.ts`,
370+
`${libName}/src/lib/btn-standalone/btn-standalone.ts`,
371371
`
372372
import { Component, Input } from '@angular/core';
373373
import { CommonModule } from '@angular/common';
374-
import { InputStandaloneComponent } from '@${projectName}/${buildLibNames.fileName}';
374+
import { InputStandalone } from '@${projectName}/${buildLibNames.fileName}';
375375
@Component({
376376
selector: '${projectName}-btn-standalone',
377377
standalone: true,
378-
imports: [CommonModule, InputStandaloneComponent],
378+
imports: [CommonModule, InputStandalone],
379379
template: '<button class="text-green-500">standlone-{{text}}</button>${projectName} <${projectName}-input-standalone></${projectName}-input-standalone>',
380380
styles: [],
381381
})
382-
export class BtnStandaloneComponent {
382+
export class BtnStandalone {
383383
@Input() text = 'something';
384384
}
385385
`
@@ -394,7 +394,7 @@ function updateBuilableLibTestsToAssertAppStyles(
394394

395395
removeFile(`${buildableLibName}/src/lib/input/input.component.cy.ts`);
396396
updateFile(
397-
`${buildableLibName}/src/lib/input-standalone/input-standalone.component.cy.ts`,
397+
`${buildableLibName}/src/lib/input-standalone/input-standalone.cy.ts`,
398398
(content) => {
399399
// app styles should now apply
400400
return content.replace('rgb(34, 197, 94)', 'rgb(255, 192, 203)');

e2e/angular/src/misc.test.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,8 @@ describe('Move Angular Project', () => {
4545
expect(moveOutput).toContain(`CREATE ${newPath}/src/main.ts`);
4646
expect(moveOutput).toContain(`CREATE ${newPath}/src/styles.css`);
4747
expect(moveOutput).toContain(`CREATE ${newPath}/src/test-setup.ts`);
48-
expect(moveOutput).toContain(
49-
`CREATE ${newPath}/src/app/app.component.html`
50-
);
51-
expect(moveOutput).toContain(`CREATE ${newPath}/src/app/app.component.ts`);
48+
expect(moveOutput).toContain(`CREATE ${newPath}/src/app/app.html`);
49+
expect(moveOutput).toContain(`CREATE ${newPath}/src/app/app.ts`);
5250
expect(moveOutput).toContain(`CREATE ${newPath}/src/app/app.config.ts`);
5351
});
5452

e2e/angular/src/module-federation.test.ts

+13-13
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,12 @@ describe('Angular Module Federation', () => {
9494
import { ${
9595
names(secondaryEntry).className
9696
}Module } from '@${proj}/${sharedLib}/${secondaryEntry}';
97-
import { AppComponent } from './app.component';
98-
import { NxWelcomeComponent } from './nx-welcome.component';
97+
import { App } from './app';
98+
import { NxWelcome } from './nx-welcome';
9999
import { RouterModule } from '@angular/router';
100100
101101
@NgModule({
102-
declarations: [AppComponent, NxWelcomeComponent],
102+
declarations: [App, NxWelcome],
103103
imports: [
104104
BrowserModule,
105105
${names(sharedLib).className}Module,
@@ -118,7 +118,7 @@ describe('Angular Module Federation', () => {
118118
),
119119
],
120120
providers: [],
121-
bootstrap: [AppComponent],
121+
bootstrap: [App],
122122
})
123123
export class AppModule {}
124124
`
@@ -132,18 +132,18 @@ describe('Angular Module Federation', () => {
132132
import { ${
133133
names(secondaryEntry).className
134134
}Module } from '@${proj}/${sharedLib}/${secondaryEntry}';
135-
import { RemoteEntryComponent } from './entry.component';
136-
import { NxWelcomeComponent } from './nx-welcome.component';
135+
import { RemoteEntry } from './entry';
136+
import { NxWelcome } from './nx-welcome';
137137
138138
@NgModule({
139-
declarations: [RemoteEntryComponent, NxWelcomeComponent],
139+
declarations: [RemoteEntry, NxWelcome],
140140
imports: [
141141
CommonModule,
142142
${names(sharedLib).className}Module,
143143
RouterModule.forChild([
144144
{
145145
path: '',
146-
component: RemoteEntryComponent,
146+
component: RemoteEntry,
147147
},
148148
]),
149149
],
@@ -301,7 +301,7 @@ test('renders remotes', async ({ page }) => {
301301

302302
// Update Host to use the module
303303
updateFile(
304-
`${host}/src/app/app.component.ts`,
304+
`${host}/src/app/app.ts`,
305305
`
306306
import { Component } from '@angular/core';
307307
import { isEven } from '${remote}/${module}';
@@ -311,7 +311,7 @@ test('renders remotes', async ({ page }) => {
311311
template: \`<div class="host">{{title}}</div>\`,
312312
standalone: true
313313
})
314-
export class AppComponent {
314+
export class App {
315315
title = \`shell is \${isEven(2) ? 'even' : 'odd'}\`;
316316
}`
317317
);
@@ -373,7 +373,7 @@ test('renders remotes', async ({ page }) => {
373373

374374
// Update Host to use the module
375375
updateFile(
376-
`${remote}/src/app/remote-entry/entry.component.ts`,
376+
`${remote}/src/app/remote-entry/entry.ts`,
377377
`
378378
import { Component } from '@angular/core';
379379
import { isEven } from '${childRemote}/${module}';
@@ -383,7 +383,7 @@ test('renders remotes', async ({ page }) => {
383383
template: \`<div class="childremote">{{title}}</div>\`,
384384
standalone: true
385385
})
386-
export class RemoteEntryComponent {
386+
export class RemoteEntry {
387387
title = \`shell is \${isEven(2) ? 'even' : 'odd'}\`;
388388
}`
389389
);
@@ -398,7 +398,7 @@ test('renders remotes', async ({ page }) => {
398398
remotes: ['${childRemote}'],
399399
exposes: {
400400
'./Routes': '${remote}/src/app/remote-entry/entry.routes.ts',
401-
'./Module': '${remote}/src/app/remote-entry/entry.component.ts',
401+
'./Module': '${remote}/src/app/remote-entry/entry.ts',
402402
},
403403
};
404404

0 commit comments

Comments
 (0)