Angular Schematics 相对路径
Posted
技术标签:
【中文标题】Angular Schematics 相对路径【英文标题】:Angular Schematics relative path 【发布时间】:2019-09-05 23:54:36 【问题描述】:我想为 Angular 创建一个自定义原理图,它将在与执行原理图相同的目录中创建一个文件。我关注了这篇文章,但我不确定如何将新文件添加到所需的目录中。 (https://developer.okta.com/blog/2019/02/13/angular-schematics#create-your-first-schematic)
例如,如果我有以下目录结构:
src/app/ !-- Angular Root
|- modules
|_ foo
|- foo.component.ts
|_ foo.component.html
|- app.component.ts
|- app.component.html
|_ app.module.ts
如果我这样做了,请执行以下命令:
> cd /src/app/modules/foo
> ng g my-component:my-component
我希望新创建/更新的文件位于 /src/app/modules/foo 目录而不是根目录中。想想 ng generate 是如何工作的。如果我从目录 /src/app/modules/foo 中执行ng g component bar
,那么将在该目录中生成一个新组件。这是我需要复制的行为。
这是我的工厂。现在它显然是用project.root
定位根目录但是我没有找到任何替代方案,如果我不提供路径,那么我会收到错误消息。如何获取当前路径(src/app/modules/foo)以存储在options.path
?
export function setupOptions(host: Tree, options: any): Tree
const workspace = getWorkspace(host);
if (!options.project)
options.project = Object.keys(workspace.projects)[0];
const project = workspace.projects[options.project];
options.path = join(normalize(project.root), 'src');
return host;
// You don't have to export the function as default. You can also have more than one rule factory
// per file.
export function myComponent(_options: any): Rule
return (tree: Tree, _context: SchematicContext) =>
setupOptions(tree, _options);
const movePath = normalize(_options.path + '/');
const templateSource = apply(url('./files/src'), [
template( ..._options ),
move(movePath),
forEach((fileEntry: FileEntry) =>
if (tree.exists(fileEntry.path))
tree.overwrite(fileEntry.path, fileEntry.content);
return fileEntry;
)
]);
const rule = mergeWith(templateSource, MergeStrategy.Overwrite);
return rule(tree, _context);
;
【问题讨论】:
这应该默认使用ng
cli。你能发布你的工厂吗?
我在上面加了工厂。
【参考方案1】:
可能这是一个丑陋的解决方案,但我找到它的唯一方法。
你必须改变树的根目录才能访问当前目录的父目录
const currentPath = (tree as any)['_backend']['_root'] ;
(tree as any)['_backend']['_root'] = '/' ;
const currentDir = tree.getDir(currentPath);
const parent = currentDir.parent ;
知道你可以访问父目录并且可以编写自己的函数来改变每一件事
查看示例
const rootModelDirectory = 'model-form-request'
export function model(_options: any): Rule
return (tree: Tree, _context: SchematicContext) =>
const currentPath = (tree as any)['_backend']['_root'] ;
(tree as any)['_backend']['_root'] = '/' ;
console.log(currentPath);
const rootdir = findParentDirectoryPath(tree.getDir(currentPath) , rootModelDirectory);
const templateSource = apply(url('./files'), [
// filter(path => path.endsWith('__name@dasherize__.module.ts.template')),
template(
...strings,
..._options
),
move(normalize(`/$rootdir/$dasherize(_options.name)/`))
]);
return mergeWith(templateSource);
;
export function findParentDirectoryPath(location :ReturnType<Tree['getDir']>, directoryName : string): string
for(const dirPath of location.subdirs)
if(new RegExp(directoryName).test(dirPath))
return `$location.path/$dirPath` ;
if(location.parent)
return findParentDirectoryPath(location.parent , directoryName);
throw new Error('root model directory not found')
【讨论】:
【参考方案2】:有些事情让我困惑了一段时间,需要提防。
'options.path' 在角度项目的根目录中执行原理图命令时将未定义。只有将目录更改为根目录的子目录,路径才可用。
【讨论】:
【参考方案3】:按照angular docs中提到的步骤进行
你会遇到一些问题。例如
1) const workspaceConfig = tree.read('/angular.json');
// 使用 'schematics' 命令时将为空,但使用 'ng g' 命令时会起作用。
2) 同样,在使用“schematics”命令时,“options.path”将是未定义的,但在使用“ng g”命令时会起作用。
上面的回复是正确的,你需要添加schema.json文件的路径,然后在你的函数中
'导出函数myComponent(_options: any): Rule '
您应该能够使用“options.path”来获取当前位置。但是,正如我提到的,在使用“原理图”命令时,我无法让它工作。我只有在使用“ng g”命令时才能让它工作。
作为一个例子,这里是我的文件
1) ..schematics/ng-generate/customComponent/schema.json
"$schema": "http://json-schema.org/schema",
"id": "GenerateCustomComponent",
"title": "Generate Custom Component",
"type": "object",
"properties":
"name":
"description": "The name for the custom component.",
"type": "string",
"x-prompt": "What is the name for the custom component?"
,
"path":
"type": "string",
"format": "path",
"description": "The path at which to create the component file, relative to the current workspace. Default is a folder with the same name as the component in the project root.",
"visible": false
,
"required": [
"name"
]
2) ..schematics/ng-generate/customComponent/schema.ts
import Schema as ComponentSChema from '@schematics/angular/component/schema';
export interface Schema extends ComponentSChema
// The name of the custom component
name: string;
2) ..schematics/ng-generate/customComponent/index.ts
import
Rule, Tree, SchematicsException,
apply, url, applyTemplates, move,
chain, mergeWith
from '@angular-devkit/schematics';
import strings, experimental, normalize from '@angular-devkit/core';
import Schema as CustomSchema from './schema';
export function generate(options: CustomSchema): Rule
return (tree: Tree) =>
const workspaceConfig = tree.read('/angular.json'); // will return null when using schematics command but will work when using ng g
console.log('workspaceConfig::', workspaceConfig);
console.log('path:', options.path); // will be undefined when using schematics command but will work when using ng g
// from now following along with angular docs with slight modifications.
if (workspaceConfig && !options.path)
const workspaceContent = workspaceConfig.toString();
console.log('workspaceContent::', workspaceContent);
const workspace: experimental.workspace.WorkspaceSchema = JSON.parse(workspaceContent);
console.log('workspace', workspace);
options.project = workspace.defaultProject;
const projectName = options.project as string;
const project = workspace.projects[projectName];
const projectType = project.projectType === 'application' ? 'app' : 'lib';
console.log('projectType::', projectType);
options.path = `$project.sourceRoot/$projectType`;
if (options.path)
// this will be used by the ng g command
const templateSource = apply(url('./files'), [
applyTemplates(
classify: strings.classify,
dasherize: strings.dasherize,
name: options.name
),
move(normalize(options.path as string))
]);
return chain([
mergeWith(templateSource)
]);
else
// this will be used by the schematics command
const templateSource = apply(url('./files'), [
applyTemplates(
classify: strings.classify,
dasherize: strings.dasherize,
name: options.name
)
]);
return chain([
mergeWith(templateSource)
]);
;
【讨论】:
【参考方案4】:将此添加到您的 schema.json
...,
"properties":
..
"path":
"type": "string",
"format": "path",
"description": "The path to create the simple schematic within.",
"visible": false
【讨论】:
以上是关于Angular Schematics 相对路径的主要内容,如果未能解决你的问题,请参考以下文章