DEV Community

Gaëtan Redin
Gaëtan Redin

Posted on • Originally published at Medium on

Story for an Angular Directive

Storybook and Angular Directive

Hey, I have just started with Storybook for angular, maybe you too. One week ago, I was just trying to write a story for a ButtonDirective and it was not so easy… So I tried and tried and now it’s okay! This article is more for Storybook/Angular beginners, just to save your time.

Context: Angular 12, StoryBook 6.3.8

I presume you already have installed storybook, if you don’t just go here.

Here’s my directive:

// button.directive.ts
@Directive({
  selector: 'button[adrButton]',
  host: {
    _class_: 'adr-button',
    '[class.adr-small]': 'size === "small"',
    '[class.adr-medium]': 'size === "medium"',
    '[class.adr-large]': 'size === "large"',
    '[class.adr-outlined]': 'outlined',
    '[class.adr-primary]': 'color === "primary"',
    '[class.adr-accent]': 'color === "accent"',
    '[class.adr-warn]': 'color === "warn"'
  }
})
_export class_ ButtonDirective {
  @Input()
  _public_ size: 'small' | 'medium' | 'large' = 'medium';

  @Input()
  _public_ outlined: _boolean_ = _false_;

  @Input()
  _public_ color?: 'primary' | 'accent' | 'warn';
}
Enter fullscreen mode Exit fullscreen mode

Basic right?

I didn’t find in the Storybook documentation how to write a story for an Angular directive. Maybe it’s beause it was first created for React, I don’t know. But the tip is to create a DummyComponent. Let me show you:

_import_ { CommonModule } _from_ '@angular/common';
_import_ { Component, Input } _from_ '@angular/core';
_import_ { _Meta_, _Story_ } _from_ '@storybook/angular';
_import_ { ButtonDirective } _from_ 'src/components/atoms/button/button.directive';

@Component({
  selector: 'adr-dummy',
  template: `
      <button adrButton [size]="size" [outlined]="outlined" [color]="color">Click</button>`
})
_class_ DummyComponent { // **(1)**
  @Input()
  _public_ size: 'small' | 'medium' | 'large' = 'medium';

  @Input()
  _public_ outlined: _boolean_ = _false_;

  @Input()
  _public_ color?: 'primary' | 'accent' | 'warn';
}

_export default_ {
  title: 'atoms/button',
  component: DummyComponent // **(2)**  **don't forget it**
  }
} _as Meta_;

_const_ Template: _Story_<DummyComponent> = (args) => ({
  props: args, 
  moduleMetadata: { // **(3)**  **don't forget it**
    declarations: [ButtonDirective], 
    imports: [CommonModule]
  }
});

_export const_ Default = Template.bind({});
Default.args = {};
Enter fullscreen mode Exit fullscreen mode

And that’s all. What have we do here?

(1) We have create our DummyComponent and set the expected template. We put inside the same inputs like in the ButtonDirective.

(2) In the Meta we set our DummyComponent.

(3) In the Template definition, we have specified the moduleMetadata.

You can try it works perfectly.

Thanks for reading.

Learn More

Discussion (0)