Angular 17.3与Storybook 8.0.8中如何使用Input Signal?
Angular 17.3 + Storybook 8.0.8:Input信号组件的故事传参问题
我在集成Storybook 8.0.8与Angular 17.3时遇到问题:组件使用Angular的input()信号定义输入属性,但Storybook故事的args要求参数类型必须为InputSignal,无法像以前那样直接传入字面量值。不想通过注入上下文的方式解决,希望找到简洁的内联写法。
复现代码
组件代码
@Component({ selector: 'app-note', template: 'A note with {{maxChars()}} maximum characters', standalone: true, }) export class NoteComponent { maxChars = input<number>(300); }
Storybook故事代码
const meta: Meta<NoteComponent> = { title: 'Shared/Note', component: NoteComponent, tags: ['autodocs'], args: { maxChars: 200 // 错误:类型“number”不能分配给类型“InputSignal<number>”。 } }; export default meta; type Story = StoryObj<NoteComponent>; export const Primary: Story = { };
注意:若在注入上下文外调用
input()(比如直接在故事中创建信号),会抛出错误:
NG0203: inputFunction() can only be used within an injection context such as a constructor, a factory function, a field initializer, or a function used with runInInjectionContext
解决方案
方案1:利用argTypes的transform转换参数
通过argTypes定义参数转换规则,将字面量值转换为符合要求的InputSignal,Storybook会自动在注入上下文内执行转换逻辑:
const meta: Meta<NoteComponent> = { title: 'Shared/Note', component: NoteComponent, tags: ['autodocs'], args: { maxChars: 200 }, argTypes: { maxChars: { transform: (value: number) => input(value), } } };
方案2:通过render函数手动绑定输入
直接在故事的render函数中使用Angular模板绑定传递参数,完全贴合组件的正常使用方式,无需处理信号类型:
export const Primary: Story = { render: (args) => ({ template: `<app-note [maxChars]="maxChars"></app-note>`, props: args, }), args: { maxChars: 200 } };
方案3:用componentWrapperDecorator统一处理
如果多个故事都需要处理类似输入信号的传参问题,可以使用装饰器包裹组件,统一绑定输入参数:
const meta: Meta<NoteComponent> = { title: 'Shared/Note', component: NoteComponent, tags: ['autodocs'], decorators: [ componentWrapperDecorator((args) => `<app-note [maxChars]="${args.maxChars}"></app-note>`) ], args: { maxChars: 200 } };
内容的提问来源于stack exchange,提问作者Xerner
相关产品推荐
相关产品推荐

