Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 537
Georg Leber Avatar asked Jul 03 '19 10:07

Georg Leber


2 Answers

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.

like image 195
matitalatina Avatar answered Oct 22 '22 01:10

matitalatina


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,
  },
});
like image 29
Eliezer Berlin Avatar answered Oct 22 '22 01:10

Eliezer Berlin