Georg Leber
Georg Leber

Reputation: 3580

Storybook with using Injection in angular module

I want to use Storybook to develop and test my UI components and release them as npm library from within the same project. This is why I encapsulate all components as a single feature module. I wanted to create a simple module which generates a form and allows some undo functionality. My problem is that Storybook cannot inject the Formbuilder Service into my component.

My setup is as follows:

The story:

storiesOf('UndoForm', module)
  .addDecorator(
    moduleMetadata({
      imports: [ReactiveFormsModule, UndoFormModule]
    }),
  )
  .add('Testform', () => ({
    template: '<mods-undo-form></mods-undo-form>'
  })
);

The UndoFormModule:

@NgModule({
  declarations: [UndoFormComponent],
  imports: [ReactiveFormsModule],
  exports: [UndoFormComponent]
})
export class UndoFormModule {}

The UndoFormComponent:

@Component({
  selector: 'mods-undo-form',
  templateUrl: './undo-form.component.html',
  styleUrls: ['./undo-form.component.scss']
})
export class UndoFormComponent implements OnInit {
  [...]
  constructor(private fb: FormBuilder) { }
  [...]
}

The error I get is:

Can't resolve all parameters for UndoFormComponent: (?).

What I found out is, that when I use the @Inject annotation explicitly, then the code works:

constructor(@Inject(FormBuilder) private fb: FormBuilder) { }

Is there any possibility to prevent the usage of the explicit annotation?

Upvotes: 8

Views: 13323

Answers (3)

Eliezer Berlin
Eliezer Berlin

Reputation: 3576

You can import it directly into the story. like so:

import { BannerV2Component } from './banner.v2.component';
import { moduleMetadata } from '@storybook/angular';


export default { 
  title: 'Banner',
  decorators: [
    moduleMetadata({
        imports: [ReactiveFormsModule, UndoFormModule],
        providers: [FormBuilder],
    })
  ]
}
export const OptionOne = () => ({
  component: BannerV2Component,
  props: {
    mainText:'Text Two',
    showBreadcrumbs:true,
  },
});

Upvotes: 2

matitalatina
matitalatina

Reputation: 211

You need to add "emitDecoratorMetadata": true in compilerOptions object in .storybook/tsconfig.json file.

So your .storybook/tsconfig.json should be like this:

{
  "extends": "../tsconfig.app.json",
  "compilerOptions": {
    "emitDecoratorMetadata": true,   <--------- Add this!
    ...
  },
  ...
}

Then make sure to restart your storybook process.

Upvotes: 13

Jayant Pareek
Jayant Pareek

Reputation: 370

You need to provide 'FormBuilder' in the providers array in moduleMetadata of the storybook decorator. This way, your storybook setup will recognise that FormBuilder is being used as an injectable dependency in your component.

Here is how I am using it in one of our stories:

storiesOf('UndoForm', module)
  .addDecorator(
    moduleMetadata({
      imports: [ReactiveFormsModule, UndoFormModule],
      providers: [FormBuilder],
    }),
  )
  .add('Testform', () => ({
    template: '<mods-undo-form></mods-undo-form>'
  })
);

Upvotes: 0

Related Questions