5

What is the best way to extend an existing Angular Schematic? I'm looking specifically at adding some default code into a component's spec file at the moment, but a more generalized answer would be appreciated.

In the tutorials I've found, they show the externalSchematic function, which seems to be on the right track, but none of them show how to update/replace that schematic's template file. I've tried just copying the templates into my schematic and applying/merging them, but that seems a little overkill. Angular's documentation on this matter also seems scarce.

Is there a way to do extend the default schematics, or will I need to do everything from scratch?

2
  • I want to back up your question cause I've been through the same problem here. Right now, to me, the hacky solution is to copy source code from @schematics/angular and tinkering them to fit my need. It's quite a frustrating and not-any-better-than-scratch workaround, but If you really need I can post it in answers. Commented Aug 13, 2019 at 9:39
  • 1
    I've moved on for the moment; I did subscribe to this issue to know when the api docs will show up for the next time, but I don't know when that will be. Commented Aug 13, 2019 at 18:04

1 Answer 1

4

I definitely agree that the documentation is sparse. The most helpful resource I found for extending existing schematics is this article: https://blog.angular.io/schematics-an-introduction-dc1dfbc2a2b2

Under the heading 'Calling Another Schematic', it has some example code on how to modify a newly create component, which seems like what you're looking for. At the end of the day, you should call the existing angular component schematic and then find the file(s) you want to modify (in your case, the .spec.ts file), and finally insert the new code you want:

import { Rule, SchematicContext, Tree, chain, externalSchematic } from '@angular-devkit/schematics';

const sText = "test to insert";

return chain([
    // Here you can modify options or do any preprocessing before calling the schematic (optional)
    (cTree: Tree, _context: SchematicContext) => {     
        return cTree;
    },

    // Call the external schematic
    externalSchematic('@schematics/angular', 'component', _options),

    // Do whatever downstream processing you need to 
    (cTree: Tree, _context: SchematicContext) => {

        // Find new component, which depends on where you put it in the tree
        // Some approaches prefer to scan the entire tree looking for the new file,
        // I prefer to narrow my search down a bit.
        cTree.getDir('.')
            .visit((sTempFilePath) => {

                if (!sTempFilePath.endsWith(dasherize(_options['name']) + '.component.spec.ts')) {
                    // Skip anything but the newly added typescript spec file
                    return;
                }

                // Now that we've found our new component file, read in the content
                const cContentBuffer = cTree.read(sTempFilePath);
                if (!cContentBuffer) {
                    return;
                }

                // Add text at beginning of file (can customize to add anywhere)
                cTree.overwrite(
                    sTempFilePath,
                    sText + cContentBuffer);

            });

        return cTree;       
    }

]);

One final note - sometimes I've found that I need to include a schema.json in my own schematic in order to utilize the angular schematics.

Hope that helps!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.