node.jsangularnpmstorybook

generate *.story.ts automatially when generating Angular component by cli


I'm considering using Storybook in Angular project. I want to generate story file for each component, but it is bothersome to make story file manually. So I want to generate story file automatically when I generate component. For that, I can restrict component generation from the cli.(ng generate component)

This is problem about command. So Angular schematics or script in package.json may be relevant.


Solution

  • You can achieve this by creating a custom Angular schematic that generates both the component and the corresponding Storybook file.

    Here's a step-by-step guide:

    1. First, install the necessary tools for creating schematics:
    npm install -g @angular-devkit/schematics-cli
    
    1. Create a new schematic project:
    schematics blank --name=my-component-storybook
    
    1. Navigate to the schematic project:
    cd my-component-storybook
    
    1. Open the my-component-storybook folder in your code editor. You will see a collection.json file. This file is used to tell the Angular CLI what schematics your collection provides.

    2. Update the collection.json file to include a schematic for generating a component:

    {
      "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
      "schematics": {
        "my-component": {
          "description": "Create a component and its corresponding Storybook file",
          "factory": "./my-component/index#myComponent"
        }
      }
    }
    
    1. Create a new folder named my-component in the src folder. Inside the my-component folder, create an index.ts file. This is where you will define the schematic.

    2. In the index.ts file, import the necessary modules and define the schematic:

    import { Rule, SchematicContext, Tree, url, apply, template, mergeWith, SchematicsException, chain } from '@angular-devkit/schematics';
    import { strings } from '@angular-devkit/core';
    
    export function myComponent(options: any): Rule {
      return (tree: Tree, _context: SchematicContext) => {
        const sourceTemplates = url('./files');
        const sourceParameterizedTemplates = apply(sourceTemplates, [
          template({
            ...options,
            ...strings
          })
        ]);
        return mergeWith(sourceParameterizedTemplates);
      };
    }
    
    1. Create a new folder named files in the my-component folder. Inside the files folder, create your component and Storybook files with placeholders for the dynamic parts:
    // __name__.component.ts
    import { Component } from '@angular/core';
    
    @Component({
      selector: '<%= dasherize(name) %>',
      templateUrl: './<%= dasherize(name) %>.component.html',
      styleUrls: ['./<%= dasherize(name) %>.component.css']
    })
    export class <%= classify(name) %>Component {}
    
    // __name__.component.stories.ts
    export default {
      title: '<%= classify(name) %>',
      component: <%= classify(name) %>Component,
    };
    
    export const <%= classify(name) %> = () => ({
      component: <%= classify(name) %>Component,
    });
    
    1. Build the schematic:
    npm run build
    
    1. Link the schematic to make it available globally:
    npm link
    
    1. Now you can use your custom schematic to generate a component and its corresponding Storybook file:
    ng generate my-component-storybook:my-component my-component-name
    

    This will generate a new component with the name my-component-name and a corresponding Storybook file.

    Remember to replace my-component-name with the actual name of your component.