typescript - Angular Schematics - agregar biblioteca a las importaciones de NgModule
Al usar Schematics para generar componentes en Angular, intentará importar el componente recién generado en el NgModule, esto es obligatorio para que el componente funcione y ahorra tiempo.
Sin embargo, al crear mis propios esquemas, no puedo encontrar una manera correcta de hacer lo mismo e importar mi biblioteca en el NgModule de app.component.ts. Al usar los esquemas ng-add, ¿cómo se puede hacer que el esquema agregue automáticamente su propia entrada en el NgModule?
El esquema necesita hacer dos cosas:
- Importa la biblioteca
- Agrégalo a las importaciones de NgModule
Antes :
@NgModule({
declarations: [],
imports: [],
exports: []
})
export class appModule { }
Después de :
import {library} from 'library';
@NgModule({
declarations: [],
imports: [library],
exports: []
})
export class appModule { }
Sé que existe una función para hacer esto en el angular devkit porque los esquemas "oficiales" para componentes y demás la usan. ¿Cómo haría lo mismo?
Respuesta #1
Para el primer caso, algo como el código a continuación te ayudará:
export function addImportStatement(tree: Tree, filePath: string, type: string, file: string): void {
let source = getTsSourceFile(tree, filePath);
const importChange = insertImport(source, filePath, type, file) as InsertChange;
if (!(importChange instanceof NoopChange)) {
const recorder = tree.beginUpdate(filePath);
recorder.insertLeft(importChange.pos, importChange.toAdd);
tree.commitUpdate(recorder);
}
}
Para el segundo, no recuerdo en este momento, pero puedes consultar el repositorio de esquemas de angular-cli para ver cómo se hace para cosas como los módulos.
¡Salud!
Respuesta #2
Aquí hay una función que utiliza la función 'addImportToModule' de los utilitarios de `@schematics/angular/utility/ast-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;
}
Al final de una de mis otras funciones que devuelven una Regla, dentro de mi llamada a chain([])....., llamé a esta función así (necesitaba agregar HttpClientModule a los imports, y si el usuario había instalado flex layout durante las opciones x-prompts, también necesitaba agregar FlexLayoutModule a los imports. Hay múltiples otras funciones utilitarias como addDependencyToModule, addExportToModule, etc., que se pueden usar para modificar cualquiera de tus archivos module.ts)
la llamada:
tree = _addImport(
'@angular/common/http',
'HttpClientModule',
_options,
tree
);
if (_options.dependencies.includes('flexLayout')) {
tree = _addImport(
'@angular/flex-layout',
'FlexLayoutModule',
_options,
tree
);
}
return tree;
Esto agregó con éxito ambos módulos a mis importaciones: [] en app.module, así como las declaraciones de importación en la parte superior. También hay una función de utilidad 'buildRelativePath' de '@schematics/angular/utility/find-module', que puede ayudar si necesitas construir rutas relativas desde donde se encuentre el módulo con el que estás trabajando.
