Skip to content

Commit 5539d75

Browse files
crisbetoangular-robot[bot]
authored andcommitted
fix(material/schematics): support standalone projects in address from schematic
Updates the `ng generate address-form` schematic to support standalone projects.
1 parent f5b5b79 commit 5539d75

File tree

5 files changed

+82
-16
lines changed

5 files changed

+82
-16
lines changed

src/material/schematics/ng-generate/address-form/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.spec.ts.template

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { NoopAnimationsModule } from '@angular/platform-browser/animations';<% if(!standalone) { %>
23
import { ReactiveFormsModule } from '@angular/forms';
3-
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
44
import { MatButtonModule } from '@angular/material/button';
55
import { MatCardModule } from '@angular/material/card';
66
import { MatInputModule } from '@angular/material/input';
77
import { MatRadioModule } from '@angular/material/radio';
8-
import { MatSelectModule } from '@angular/material/select';
8+
import { MatSelectModule } from '@angular/material/select';<% } %>
99

1010
import { <%= classify(name) %>Component } from './<%= dasherize(name) %>.component';
1111

@@ -14,8 +14,9 @@ describe('<%= classify(name) %>Component', () => {
1414
let fixture: ComponentFixture<<%= classify(name) %>Component>;
1515

1616
beforeEach(waitForAsync(() => {
17-
TestBed.configureTestingModule({
18-
declarations: [ <%= classify(name) %>Component ],
17+
TestBed.configureTestingModule({<% if(standalone) { %>
18+
imports: [NoopAnimationsModule]<% } else { %>
19+
declarations: [<%= classify(name) %>Component],
1920
imports: [
2021
NoopAnimationsModule,
2122
ReactiveFormsModule,
@@ -24,7 +25,7 @@ describe('<%= classify(name) %>Component', () => {
2425
MatInputModule,
2526
MatRadioModule,
2627
MatSelectModule,
27-
]
28+
]<% } %>
2829
}).compileComponents();
2930
}));
3031

src/material/schematics/ng-generate/address-form/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.ts.template

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1-
import { Component<% if(!!viewEncapsulation) { %>, ViewEncapsulation<% }%><% if(changeDetection !== 'Default') { %>, ChangeDetectionStrategy<% }%> } from '@angular/core';
1+
import { Component, inject<% if(!!viewEncapsulation) { %>, ViewEncapsulation<% }%><% if(changeDetection !== 'Default') { %>, ChangeDetectionStrategy<% }%> } from '@angular/core';
2+
<% if(standalone) { %>
3+
import { ReactiveFormsModule, FormBuilder, Validators } from '@angular/forms';
4+
import { MatInputModule } from '@angular/material/input';
5+
import { MatButtonModule } from '@angular/material/button';
6+
import { MatSelectModule } from '@angular/material/select';
7+
import { MatRadioModule } from '@angular/material/radio';
8+
import { MatCardModule } from '@angular/material/card';
9+
<% } else { %>
210
import { FormBuilder, Validators } from '@angular/forms';
11+
<% } %>
312

413
@Component({
514
selector: '<%= selector %>',<% if(inlineTemplate) { %>
@@ -12,9 +21,19 @@ import { FormBuilder, Validators } from '@angular/forms';
1221
`]<% } else { %>
1322
styleUrls: ['./<%= dasherize(name) %>.component.<%= style %>']<% } %><% if(!!viewEncapsulation) { %>,
1423
encapsulation: ViewEncapsulation.<%= viewEncapsulation %><% } if (changeDetection !== 'Default') { %>,
15-
changeDetection: ChangeDetectionStrategy.<%= changeDetection %><% } %>
24+
changeDetection: ChangeDetectionStrategy.<%= changeDetection %><% } %><% if(standalone) { %>,
25+
standalone: true,
26+
imports: [
27+
MatInputModule,
28+
MatButtonModule,
29+
MatSelectModule,
30+
MatRadioModule,
31+
MatCardModule,
32+
ReactiveFormsModule
33+
]<% } %>
1634
})
1735
export class <%= classify(name) %>Component {
36+
private fb = inject(FormBuilder);
1837
addressForm = this.fb.group({
1938
company: null,
2039
firstName: [null, Validators.required],
@@ -93,8 +112,6 @@ export class <%= classify(name) %>Component {
93112
{name: 'Wyoming', abbreviation: 'WY'}
94113
];
95114

96-
constructor(private fb: FormBuilder) {}
97-
98115
onSubmit(): void {
99116
alert('Thanks!');
100117
}

src/material/schematics/ng-generate/address-form/index.spec.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,45 @@ describe('Material address-form schematic', () => {
5050
).toBeRejectedWithError(/required property 'name'/);
5151
});
5252

53+
describe('standalone option', () => {
54+
it('should generate a standalone component', async () => {
55+
const app = await createTestApp(runner);
56+
const tree = await runner.runSchematic(
57+
'address-form',
58+
{...baseOptions, standalone: true},
59+
app,
60+
);
61+
const module = getFileContent(tree, '/projects/material/src/app/app.module.ts');
62+
const content = getFileContent(tree, '/projects/material/src/app/foo/foo.component.ts');
63+
const requiredModules = [
64+
'MatInputModule',
65+
'MatButtonModule',
66+
'MatSelectModule',
67+
'MatRadioModule',
68+
'ReactiveFormsModule',
69+
];
70+
71+
requiredModules.forEach(name => {
72+
expect(module).withContext('Module should not import dependencies').not.toContain(name);
73+
expect(content).withContext('Component should import dependencies').toContain(name);
74+
});
75+
76+
expect(module).not.toContain('FooComponent');
77+
expect(content).toContain('standalone: true');
78+
expect(content).toContain('imports: [');
79+
});
80+
81+
it('should infer the standalone option from the project structure', async () => {
82+
const app = await createTestApp(runner, {standalone: true});
83+
const tree = await runner.runSchematic('address-form', baseOptions, app);
84+
const component = getFileContent(tree, '/projects/material/src/app/foo/foo.component.ts');
85+
86+
expect(tree.exists('/projects/material/src/app/app.module.ts')).toBe(false);
87+
expect(component).toContain('standalone: true');
88+
expect(component).toContain('imports: [');
89+
});
90+
});
91+
5392
describe('style option', () => {
5493
it('should respect the option value', async () => {
5594
const tree = await runner.runSchematic(

src/material/schematics/ng-generate/address-form/index.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
addModuleImportToModule,
1212
buildComponent,
1313
findModuleFromOptions,
14+
isStandaloneSchematic,
1415
} from '@angular/cdk/schematics';
1516
import {Schema} from './schema';
1617

@@ -38,12 +39,16 @@ export default function (options: Schema): Rule {
3839
*/
3940
function addFormModulesToModule(options: Schema) {
4041
return async (host: Tree) => {
41-
const modulePath = (await findModuleFromOptions(host, options))!;
42-
addModuleImportToModule(host, modulePath, 'MatInputModule', '@angular/material/input');
43-
addModuleImportToModule(host, modulePath, 'MatButtonModule', '@angular/material/button');
44-
addModuleImportToModule(host, modulePath, 'MatSelectModule', '@angular/material/select');
45-
addModuleImportToModule(host, modulePath, 'MatRadioModule', '@angular/material/radio');
46-
addModuleImportToModule(host, modulePath, 'MatCardModule', '@angular/material/card');
47-
addModuleImportToModule(host, modulePath, 'ReactiveFormsModule', '@angular/forms');
42+
const isStandalone = await isStandaloneSchematic(host, options);
43+
44+
if (!isStandalone) {
45+
const modulePath = (await findModuleFromOptions(host, options))!;
46+
addModuleImportToModule(host, modulePath, 'MatInputModule', '@angular/material/input');
47+
addModuleImportToModule(host, modulePath, 'MatButtonModule', '@angular/material/button');
48+
addModuleImportToModule(host, modulePath, 'MatSelectModule', '@angular/material/select');
49+
addModuleImportToModule(host, modulePath, 'MatRadioModule', '@angular/material/radio');
50+
addModuleImportToModule(host, modulePath, 'MatCardModule', '@angular/material/card');
51+
addModuleImportToModule(host, modulePath, 'ReactiveFormsModule', '@angular/forms');
52+
}
4853
};
4954
}

src/material/schematics/ng-generate/address-form/schema.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939
"type": "boolean",
4040
"alias": "t"
4141
},
42+
"standalone": {
43+
"description": "Whether the generated component is standalone.",
44+
"type": "boolean"
45+
},
4246
"viewEncapsulation": {
4347
"description": "Specifies the view encapsulation strategy.",
4448
"enum": ["Emulated", "None"],

0 commit comments

Comments
 (0)