0

I have a simple schematic running that proves how schematics work as described in https://angular.io/guide/schematics-for-libraries

My next step is to do something relevent to my project using the schematic - What I want is to add a directive to all of my HTML angular templates in my application

For example if there is a HTML file that has content like this

<input name="input" [(ngModel)]="input" />

after running the schematic (adds the directive)

<input appInput name="input" [(ngModel)]="input" />

From the documentation or otherwise, I am unable to see how to loop through all the files and make this change to each file. Are there any examples/pointers for this use case?

I know ng update does it for migration from NG7 => NG8 to add this to the @ViewChild /** TO DO - static flag is mandatory */ but not able to narrow down the code for this.

Basically, what can I do here to get a handle to all the HTML files

export function appInputs(_options: any): Rule {
  return (tree: Tree, _context: SchematicContext) => {
  console.log('schematic called');
  const workspaceConfig = tree.read('/angular.json');
  // convert workspace to string
  if (workspaceConfig) {
    const workspaceContent = workspaceConfig.toString();

    // parse workspace string into JSON object
    const workspace: experimental.workspace.WorkspaceSchema = JSON.parse(workspaceContent);
    console.log(workspace);
  }

  return tree;
};
}
4

2 回答 2

0

是的,这没有很好的记录。

不幸的是,你不能使用像 jsdom 这样的 JavaScript AST 工具来修改 Angular 模板。serialize(..) 方法会破坏你的指令、事件、方法和标签注释——或者只是无法序列化。

也就是说,您仍然可以使用像 jsdom 这样的 JS AST 工具来定位您希望修改的元素的文件位置、偏移位置,然后使用原理图记录器进行这些修改。

就像是

    // get the length -- from the begining to where the attr should go
    const INPUT_OFFSET = '<input'.length;

    const buffer = tree.read(FILE_PATH);
    const content = buffer.toString();

    // make sure you explictly tell fsdom to use includeNodeLocations
    const dom = new FSDOM(content, { includeNodeLocations: true });
    const elements = dom.window.document.querySelectorAll('input');

    // use the schematics tree recorder to update
    // we wont use the serialize(..) method of fsdom
    const recorder = tree.beginUpdate(FILE_PATH);

    elements.forEach(element => {
      // get the location in the source HTML of the element
      const locations = dom.nodeLocation(element);

      if (locations) {
        // add the directive, keep the white space on either side
        recorder.insertLeft(locations.startOffset + INPUT_OFFSET, ' appInput ');
      }
    });


    // all updates are committed without interfering with each offset
    tree.commitUpdate(recorder);

    return tree;
于 2020-04-27T10:10:42.623 回答
0

即使问题很老,这也可能是一个答案: https ://blog.angular.io/schematics-an-introduction-dc1dfbc2a2b2

基本上,阅读 Tree 接口 API,有一些方法可以使用,希望对您有所帮助:

tree.getDir(options.sourceDir)
          .visit(filePath => {
于 2020-03-03T17:09:00.423 回答