Skip to content

Commit e4552da

Browse files
crisbetoangular-robot[bot]
authored andcommitted
fix(material/schematics): support standalone projects in tree schematic
Updates the `ng generate tree` schematic to support standalone projects.
1 parent 9c32902 commit e4552da

File tree

5 files changed

+57
-12
lines changed

5 files changed

+57
-12
lines changed

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
1-
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
1+
import { <% if(!standalone) { %>waitForAsync, <% } %>ComponentFixture, TestBed } from '@angular/core/testing';<% if(!standalone) { %>
22
import { MatButtonModule } from '@angular/material/button';
33
import { MatIconModule } from '@angular/material/icon';
4-
import { MatTreeModule } from '@angular/material/tree';
4+
import { MatTreeModule } from '@angular/material/tree';<% } %>
55

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

88
describe('<%= classify(name) %>Component', () => {
99
let component: <%= classify(name) %>Component;
10-
let fixture: ComponentFixture<<%= classify(name) %>Component>;
10+
let fixture: ComponentFixture<<%= classify(name) %>Component>;<% if(!standalone) { %>
1111

1212
beforeEach(waitForAsync(() => {
1313
TestBed.configureTestingModule({
14-
declarations: [ <%= classify(name) %>Component ],
14+
declarations: [<%= classify(name) %>Component],
1515
imports: [
1616
MatButtonModule,
1717
MatIconModule,
1818
MatTreeModule,
1919
]
2020
}).compileComponents();
21-
}));
21+
}));<% } %>
2222

2323
beforeEach(() => {
2424
fixture = TestBed.createComponent(<%= classify(name) %>Component);

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { Component<% if (!!viewEncapsulation) { %>, ViewEncapsulation<% }%><% if (changeDetection !== 'Default') { %>, ChangeDetectionStrategy<% }%> } from '@angular/core';
2-
import { MatTreeFlatDataSource, MatTreeFlattener } from '@angular/material/tree';
3-
import { FlatTreeControl } from '@angular/cdk/tree';
2+
import { <% if(standalone) { %>MatTreeModule, <% } %>MatTreeFlatDataSource, MatTreeFlattener } from '@angular/material/tree';
3+
import { FlatTreeControl } from '@angular/cdk/tree';<% if(standalone) { %>
4+
import { MatButtonModule } from '@angular/material/button';
5+
import { MatIconModule } from '@angular/material/icon';<% } %>
46
import { files } from './example-data';
57

68
/** File node data with possible child nodes. */
@@ -32,7 +34,9 @@ export interface FlatTreeNode {
3234
`]<% } else { %>
3335
styleUrls: ['./<%= dasherize(name) %>.component.<%= style %>']<% } %><% if(!!viewEncapsulation) { %>,
3436
encapsulation: ViewEncapsulation.<%= viewEncapsulation %><% } if (changeDetection !== 'Default') { %>,
35-
changeDetection: ChangeDetectionStrategy.<%= changeDetection %><% } %>
37+
changeDetection: ChangeDetectionStrategy.<%= changeDetection %><% } %><% if(standalone) { %>,
38+
standalone: true,
39+
imports: [MatTreeModule, MatButtonModule, MatIconModule]<% } %>
3640
})
3741
export class <%= classify(name) %>Component {
3842

src/material/schematics/ng-generate/tree/index.spec.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,38 @@ describe('Material tree schematic', () => {
4848
).toBeRejectedWithError(/required property 'name'/);
4949
});
5050

51+
describe('standalone option', () => {
52+
it('should generate a standalone component', async () => {
53+
const app = await createTestApp(runner);
54+
const tree = await runner.runSchematic('tree', {...baseOptions, standalone: true}, app);
55+
const module = getFileContent(tree, '/projects/material/src/app/app.module.ts');
56+
const component = getFileContent(tree, '/projects/material/src/app/foo/foo.component.ts');
57+
const requiredModules = ['MatTreeModule', 'MatButtonModule', 'MatIconModule'];
58+
59+
requiredModules.forEach(name => {
60+
expect(module).withContext('Module should not import dependencies').not.toContain(name);
61+
expect(component).withContext('Component should import dependencies').toContain(name);
62+
});
63+
64+
expect(module).not.toContain('FooComponent');
65+
expect(component).toContain('standalone: true');
66+
expect(component).toContain('imports: [');
67+
});
68+
69+
it('should infer the standalone option from the project structure', async () => {
70+
const app = await createTestApp(runner, {standalone: true});
71+
const tree = await runner.runSchematic('tree', baseOptions, app);
72+
const componentContent = getFileContent(
73+
tree,
74+
'/projects/material/src/app/foo/foo.component.ts',
75+
);
76+
77+
expect(tree.exists('/projects/material/src/app/app.module.ts')).toBe(false);
78+
expect(componentContent).toContain('standalone: true');
79+
expect(componentContent).toContain('imports: [');
80+
});
81+
});
82+
5183
describe('style option', () => {
5284
it('should respect the option value', async () => {
5385
const tree = await runner.runSchematic(

src/material/schematics/ng-generate/tree/index.ts

Lines changed: 9 additions & 4 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,9 +39,13 @@ export default function (options: Schema): Rule {
3839
*/
3940
function addTreeModulesToModule(options: Schema) {
4041
return async (host: Tree) => {
41-
const modulePath = (await findModuleFromOptions(host, options))!;
42-
addModuleImportToModule(host, modulePath, 'MatTreeModule', '@angular/material/tree');
43-
addModuleImportToModule(host, modulePath, 'MatIconModule', '@angular/material/icon');
44-
addModuleImportToModule(host, modulePath, 'MatButtonModule', '@angular/material/button');
42+
const isStandalone = await isStandaloneSchematic(host, options);
43+
44+
if (!isStandalone) {
45+
const modulePath = (await findModuleFromOptions(host, options))!;
46+
addModuleImportToModule(host, modulePath, 'MatTreeModule', '@angular/material/tree');
47+
addModuleImportToModule(host, modulePath, 'MatIconModule', '@angular/material/icon');
48+
addModuleImportToModule(host, modulePath, 'MatButtonModule', '@angular/material/button');
49+
}
4550
};
4651
}

src/material/schematics/ng-generate/tree/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)