From f8fad4f079199c56f671447cf0ef54bae9841270 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Sat, 22 Apr 2023 08:24:43 +0200 Subject: [PATCH] fix(material/schematics): support standalone projects in address from schematic Updates the `ng generate address-form` schematic to support standalone projects. (cherry picked from commit 5539d75fdd885045792d63a714c46c12ed413b55) --- ...ame@dasherize__.component.spec.ts.template | 11 +++--- .../__name@dasherize__.component.ts.template | 25 ++++++++++-- .../ng-generate/address-form/index.spec.ts | 39 +++++++++++++++++++ .../ng-generate/address-form/index.ts | 19 +++++---- .../ng-generate/address-form/schema.json | 4 ++ 5 files changed, 82 insertions(+), 16 deletions(-) diff --git a/src/material/schematics/ng-generate/address-form/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.spec.ts.template b/src/material/schematics/ng-generate/address-form/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.spec.ts.template index 6a43509844c9..9903203b0c73 100644 --- a/src/material/schematics/ng-generate/address-form/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.spec.ts.template +++ b/src/material/schematics/ng-generate/address-form/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.spec.ts.template @@ -1,11 +1,11 @@ import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations';<% if(!standalone) { %> import { ReactiveFormsModule } from '@angular/forms'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; import { MatInputModule } from '@angular/material/input'; import { MatRadioModule } from '@angular/material/radio'; -import { MatSelectModule } from '@angular/material/select'; +import { MatSelectModule } from '@angular/material/select';<% } %> import { <%= classify(name) %>Component } from './<%= dasherize(name) %>.component'; @@ -14,8 +14,9 @@ describe('<%= classify(name) %>Component', () => { let fixture: ComponentFixture<<%= classify(name) %>Component>; beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ <%= classify(name) %>Component ], + TestBed.configureTestingModule({<% if(standalone) { %> + imports: [NoopAnimationsModule]<% } else { %> + declarations: [<%= classify(name) %>Component], imports: [ NoopAnimationsModule, ReactiveFormsModule, @@ -24,7 +25,7 @@ describe('<%= classify(name) %>Component', () => { MatInputModule, MatRadioModule, MatSelectModule, - ] + ]<% } %> }).compileComponents(); })); diff --git a/src/material/schematics/ng-generate/address-form/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.ts.template b/src/material/schematics/ng-generate/address-form/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.ts.template index b0194de05550..430516a9afb9 100644 --- a/src/material/schematics/ng-generate/address-form/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.ts.template +++ b/src/material/schematics/ng-generate/address-form/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.ts.template @@ -1,5 +1,14 @@ -import { Component<% if(!!viewEncapsulation) { %>, ViewEncapsulation<% }%><% if(changeDetection !== 'Default') { %>, ChangeDetectionStrategy<% }%> } from '@angular/core'; +import { Component, inject<% if(!!viewEncapsulation) { %>, ViewEncapsulation<% }%><% if(changeDetection !== 'Default') { %>, ChangeDetectionStrategy<% }%> } from '@angular/core'; +<% if(standalone) { %> +import { ReactiveFormsModule, FormBuilder, Validators } from '@angular/forms'; +import { MatInputModule } from '@angular/material/input'; +import { MatButtonModule } from '@angular/material/button'; +import { MatSelectModule } from '@angular/material/select'; +import { MatRadioModule } from '@angular/material/radio'; +import { MatCardModule } from '@angular/material/card'; +<% } else { %> import { FormBuilder, Validators } from '@angular/forms'; +<% } %> @Component({ selector: '<%= selector %>',<% if(inlineTemplate) { %> @@ -12,9 +21,19 @@ import { FormBuilder, Validators } from '@angular/forms'; `]<% } else { %> styleUrls: ['./<%= dasherize(name) %>.component.<%= style %>']<% } %><% if(!!viewEncapsulation) { %>, encapsulation: ViewEncapsulation.<%= viewEncapsulation %><% } if (changeDetection !== 'Default') { %>, - changeDetection: ChangeDetectionStrategy.<%= changeDetection %><% } %> + changeDetection: ChangeDetectionStrategy.<%= changeDetection %><% } %><% if(standalone) { %>, + standalone: true, + imports: [ + MatInputModule, + MatButtonModule, + MatSelectModule, + MatRadioModule, + MatCardModule, + ReactiveFormsModule + ]<% } %> }) export class <%= classify(name) %>Component { + private fb = inject(FormBuilder); addressForm = this.fb.group({ company: null, firstName: [null, Validators.required], @@ -93,8 +112,6 @@ export class <%= classify(name) %>Component { {name: 'Wyoming', abbreviation: 'WY'} ]; - constructor(private fb: FormBuilder) {} - onSubmit(): void { alert('Thanks!'); } diff --git a/src/material/schematics/ng-generate/address-form/index.spec.ts b/src/material/schematics/ng-generate/address-form/index.spec.ts index f8e973678656..daa108275655 100644 --- a/src/material/schematics/ng-generate/address-form/index.spec.ts +++ b/src/material/schematics/ng-generate/address-form/index.spec.ts @@ -50,6 +50,45 @@ describe('Material address-form schematic', () => { ).toBeRejectedWithError(/required property 'name'/); }); + describe('standalone option', () => { + it('should generate a standalone component', async () => { + const app = await createTestApp(runner); + const tree = await runner.runSchematic( + 'address-form', + {...baseOptions, standalone: true}, + app, + ); + const module = getFileContent(tree, '/projects/material/src/app/app.module.ts'); + const content = getFileContent(tree, '/projects/material/src/app/foo/foo.component.ts'); + const requiredModules = [ + 'MatInputModule', + 'MatButtonModule', + 'MatSelectModule', + 'MatRadioModule', + 'ReactiveFormsModule', + ]; + + requiredModules.forEach(name => { + expect(module).withContext('Module should not import dependencies').not.toContain(name); + expect(content).withContext('Component should import dependencies').toContain(name); + }); + + expect(module).not.toContain('FooComponent'); + expect(content).toContain('standalone: true'); + expect(content).toContain('imports: ['); + }); + + it('should infer the standalone option from the project structure', async () => { + const app = await createTestApp(runner, {standalone: true}); + const tree = await runner.runSchematic('address-form', baseOptions, app); + const component = getFileContent(tree, '/projects/material/src/app/foo/foo.component.ts'); + + expect(tree.exists('/projects/material/src/app/app.module.ts')).toBe(false); + expect(component).toContain('standalone: true'); + expect(component).toContain('imports: ['); + }); + }); + describe('style option', () => { it('should respect the option value', async () => { const tree = await runner.runSchematic( diff --git a/src/material/schematics/ng-generate/address-form/index.ts b/src/material/schematics/ng-generate/address-form/index.ts index 83700133efe5..6f773846115a 100644 --- a/src/material/schematics/ng-generate/address-form/index.ts +++ b/src/material/schematics/ng-generate/address-form/index.ts @@ -11,6 +11,7 @@ import { addModuleImportToModule, buildComponent, findModuleFromOptions, + isStandaloneSchematic, } from '@angular/cdk/schematics'; import {Schema} from './schema'; @@ -38,12 +39,16 @@ export default function (options: Schema): Rule { */ function addFormModulesToModule(options: Schema) { return async (host: Tree) => { - const modulePath = (await findModuleFromOptions(host, options))!; - addModuleImportToModule(host, modulePath, 'MatInputModule', '@angular/material/input'); - addModuleImportToModule(host, modulePath, 'MatButtonModule', '@angular/material/button'); - addModuleImportToModule(host, modulePath, 'MatSelectModule', '@angular/material/select'); - addModuleImportToModule(host, modulePath, 'MatRadioModule', '@angular/material/radio'); - addModuleImportToModule(host, modulePath, 'MatCardModule', '@angular/material/card'); - addModuleImportToModule(host, modulePath, 'ReactiveFormsModule', '@angular/forms'); + const isStandalone = await isStandaloneSchematic(host, options); + + if (!isStandalone) { + const modulePath = (await findModuleFromOptions(host, options))!; + addModuleImportToModule(host, modulePath, 'MatInputModule', '@angular/material/input'); + addModuleImportToModule(host, modulePath, 'MatButtonModule', '@angular/material/button'); + addModuleImportToModule(host, modulePath, 'MatSelectModule', '@angular/material/select'); + addModuleImportToModule(host, modulePath, 'MatRadioModule', '@angular/material/radio'); + addModuleImportToModule(host, modulePath, 'MatCardModule', '@angular/material/card'); + addModuleImportToModule(host, modulePath, 'ReactiveFormsModule', '@angular/forms'); + } }; } diff --git a/src/material/schematics/ng-generate/address-form/schema.json b/src/material/schematics/ng-generate/address-form/schema.json index f6c11bbf4d02..751ecadde744 100644 --- a/src/material/schematics/ng-generate/address-form/schema.json +++ b/src/material/schematics/ng-generate/address-form/schema.json @@ -39,6 +39,10 @@ "type": "boolean", "alias": "t" }, + "standalone": { + "description": "Whether the generated component is standalone.", + "type": "boolean" + }, "viewEncapsulation": { "description": "Specifies the view encapsulation strategy.", "enum": ["Emulated", "None"],