在 angular 模块中使用注入的故事书

Storybook with using Injection in angular module

我想使用 Storybook 来开发和测试我的 UI 组件,并在同一项目中将它们作为 npm 库发布。这就是我将所有组件封装为一个功能模块的原因。我想创建一个简单的模块来生成一个表单并允许一些撤消功能。我的问题是 Storybook 无法将 Formbuilder 服务注入到我的组件中。

我的设置如下:

故事:

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

UndoFormModule:

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

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) { }
  [...]
}

我得到的错误是:

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

我发现,当我明确使用 @Inject 注释时,代码有效:

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

是否有可能阻止使用显式注释?

您需要在故事书装饰器的 moduleMetadata 的 providers 数组中提供 'FormBuilder'。这样,您的故事书设置将识别 FormBuilder 被用作组件中的可注入依赖项。

以下是我如何在我们的一个故事中使用它:

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

您需要在 .storybook/tsconfig.json 文件的 compilerOptions 对象中添加 "emitDecoratorMetadata": true

所以你的.storybook/tsconfig.json应该是这样的:

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

然后确保重新启动您的故事书进程。

您可以直接将其导入到故事中。像这样:

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,
  },
});