Skip to content

Commit 86c9e03

Browse files
committed
feat(schematics): customize component creation
1 parent d421b2f commit 86c9e03

File tree

3 files changed

+95
-6
lines changed

3 files changed

+95
-6
lines changed

schematics/component/index.ts

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { strings } from '@angular-devkit/core';
22
import { Rule, SchematicsException, Tree, apply, branchAndMerge, chain, filter, mergeWith, move, noop, template, url } from '@angular-devkit/schematics';
3-
import { addSymbolToNgModuleMetadata } from '@schematics/angular/utility/ast-utils';
3+
import { addDeclarationToModule, addEntryComponentToModule, addExportToModule, addSymbolToNgModuleMetadata } from '@schematics/angular/utility/ast-utils';
44
import { InsertChange } from '@schematics/angular/utility/change';
55
import { buildRelativePath } from '@schematics/angular/utility/find-module';
66
import { parseName } from '@schematics/angular/utility/parse-name';
@@ -27,7 +27,79 @@ function addImportToNgModule(options: ComponentOptions): Rule {
2727
if (!options.module) {
2828
return host;
2929
}
30+
if (!options.createModule && options.module) {
31+
addImportToDeclarations(host, options);
32+
}
33+
if (options.createModule && options.module) {
34+
addImportToImports(host, options);
35+
}
36+
return host;
37+
};
38+
}
39+
40+
function addImportToDeclarations(host: Tree, options: ComponentOptions): void {
41+
if (options.module) {
42+
const modulePath = options.module;
43+
let source = readIntoSourceFile(host, modulePath);
44+
45+
const componentPath = `/${options.path}/`
46+
+ (options.flat ? '' : strings.dasherize(options.name) + '/')
47+
+ strings.dasherize(options.name)
48+
+ '.component';
49+
const relativePath = buildRelativePath(modulePath, componentPath);
50+
const classifiedName = strings.classify(`${options.name}Component`);
51+
const declarationChanges = addDeclarationToModule(source,
52+
modulePath,
53+
classifiedName,
54+
relativePath);
55+
56+
const declarationRecorder = host.beginUpdate(modulePath);
57+
for (const change of declarationChanges) {
58+
if (change instanceof InsertChange) {
59+
declarationRecorder.insertLeft(change.pos, change.toAdd);
60+
}
61+
}
62+
host.commitUpdate(declarationRecorder);
63+
64+
if (options.export) {
65+
// Need to refresh the AST because we overwrote the file in the host.
66+
source = readIntoSourceFile(host, modulePath);
3067

68+
const exportRecorder = host.beginUpdate(modulePath);
69+
const exportChanges = addExportToModule(source, modulePath,
70+
strings.classify(`${options.name}Component`),
71+
relativePath);
72+
73+
for (const change of exportChanges) {
74+
if (change instanceof InsertChange) {
75+
exportRecorder.insertLeft(change.pos, change.toAdd);
76+
}
77+
}
78+
host.commitUpdate(exportRecorder);
79+
}
80+
81+
if (options.entryComponent) {
82+
// Need to refresh the AST because we overwrote the file in the host.
83+
source = readIntoSourceFile(host, modulePath);
84+
85+
const entryComponentRecorder = host.beginUpdate(modulePath);
86+
const entryComponentChanges = addEntryComponentToModule(
87+
source, modulePath,
88+
strings.classify(`${options.name}Component`),
89+
relativePath);
90+
91+
for (const change of entryComponentChanges) {
92+
if (change instanceof InsertChange) {
93+
entryComponentRecorder.insertLeft(change.pos, change.toAdd);
94+
}
95+
}
96+
host.commitUpdate(entryComponentRecorder);
97+
}
98+
}
99+
}
100+
101+
function addImportToImports(host: Tree, options: ComponentOptions): void {
102+
if (options.module) {
31103
const modulePath = options.module;
32104
const moduleSource = readIntoSourceFile(host, modulePath);
33105

@@ -47,8 +119,7 @@ function addImportToNgModule(options: ComponentOptions): Rule {
47119
}
48120
}
49121
host.commitUpdate(importRecorder);
50-
return host;
51-
};
122+
}
52123
}
53124

54125
export default function(options: ComponentOptions): Rule {
@@ -73,6 +144,7 @@ export default function(options: ComponentOptions): Rule {
73144

74145
const templateSource = apply(url('./files'), [
75146
options.spec ? noop() : filter(p => !p.endsWith('.spec.ts')),
147+
options.createModule ? noop() : filter(p => !p.endsWith('.module.ts')),
76148
template({
77149
...strings,
78150
'if-flat': (s: string) => options.flat ? '' : s,

schematics/component/schema.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,8 @@ export interface Schema {
77
spec?: boolean;
88
flat?: boolean;
99
selector?: string;
10+
createModule?: boolean;
1011
module?: string;
12+
export?: boolean;
13+
entryComponent?: boolean;
1114
}

schematics/component/schema.json

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,24 @@
5959
"format": "html-selector",
6060
"description": "The selector to use for the page"
6161
},
62-
"module": {
62+
"createModule": {
63+
"type": "boolean",
64+
"description": "Allows creating a module for the component",
65+
"default": false
66+
},
67+
"module": {
6368
"type": "string",
64-
"description": "Allows specification of the declaring module",
65-
"alias": "m"
69+
"description": "Allows adding to a modules imports or declarations"
70+
},
71+
"export": {
72+
"type": "boolean",
73+
"default": false,
74+
"description": "When true, the declaring NgModule exports this component."
75+
},
76+
"entryComponent": {
77+
"type": "boolean",
78+
"default": false,
79+
"description": "When true, the new component is the entry component of the declaring NgModule."
6680
}
6781
},
6882
"required": []

0 commit comments

Comments
 (0)