Here is a function that uses the 'addImportToModule' function from `@schematics/angular/utility/ast-utils' utils..
function _addImport(
importPath: string,
importName: string,
_options: Partial<Schema>,
tree: Tree
): Tree {
const appModulePath = `/${_options.projectName}/src/app/app.module.ts`;
const appModuleFile = tree.read(normalize(appModulePath)).toString('utf-8');
if (!appModuleFile) {
throw new SchematicsException('app.module.ts not found');
}
const result = new AddToModuleContext();
result.source = ts.createSourceFile(
appModulePath,
appModuleFile,
ts.ScriptTarget.Latest,
true
);
result.relativePath = importPath;
result.classifiedName = importName;
const importsChanges = addImportToModule(
result.source,
appModulePath,
result.classifiedName,
result.relativePath
);
const importRecorder = tree.beginUpdate(appModulePath);
for (const change of importsChanges) {
if (change instanceof InsertChange) {
importRecorder.insertLeft(change.pos, change.toAdd);
}
}
tree.commitUpdate(importRecorder);
return tree;
}
At the end of one of my other functions that return a Rule, inside my call to chain([])....., I called this function like so (I needed to add the HttpClientModule to imports, and if the user installed flex layout during the options x-prompts, I needed to add the FlexLayoutModule to imports as well.
There are multiple other utility functions such as addDependencyToModule, addExportToModule, etc, that can be used to tweak any of your module.ts files
the call:
tree = _addImport(
'@angular/common/http',
'HttpClientModule',
_options,
tree
);
if (_options.dependencies.includes('flexLayout')) {
tree = _addImport(
'@angular/flex-layout',
'FlexLayoutModule',
_options,
tree
);
}
return tree;
This successfully added both modules to my imports: [] in app.module, as well as the import statements up top. There is also a utility function 'buildRelativePath' from '@schematics/angular/utility/find-module, which can help if you need to build relative paths from wherever you module you are working with is located.