I am developping some components and custom form elements that I want to have on Storybook.
To be complete, I want the stories to use FormControl
and FormGroup
to show some real use case.
I have the following story :
export const Dropdown: Story = {
args: {
label: 'Dropdown',
placeholder: 'Placeholder',
},
render: (args) => ({
props: {
...args,
formGroup: new FormGroup({
dropdown: new FormControl("item2", Validators.required),
}),
},
template: `
<form [formGroup]="formGroup">
<gai-dropdown ${argsToTemplate(args)} style="width: 200px" formControlName="dropdown">
<gai-option value="item1" label="Item 1"/>
<gai-option value="item2" label="Item 2"/>
<gai-option value="item3" label="Item 3"/>
<gai-option value="item4" label="Item 4">
<ng-template>Avec template</ng-template>
</gai-option>
</gai-dropdown>
</form>
`
}),
};
And the binding does work because the component displays as follows :
But if I interact with the dropdown to change the value, clear it or anything, the FormControl
doesn't change.
I am at a loss here. Everything works perfectly when using the component outside of Storybook.
In my dropdown component I register the onChange
callback like this :
registerOnChange(fn: any): void {
this.onChangeForm = fn;
}
And I had declared onChangeForm
like this : onChangeForm: any = () => {}
.
I migrated it to a property with a getter and setter and it now works. I have no idea why though.
It turns out it was a weird interaction with Storybook Controls. The onChange
method was overriden by Storybook controls for some reason.
Renaming the method to something random and not onSomething
made it work. So I ended up excluding the onChange
and onTouched
method from the controls like this :
parameters: {
controls: {
exclude: ['onBlur', 'onChange', 'onTouched'],
}
},
EDIT: It was actually the "Actions" addon that was configured to register actions for every method starting with "on". It was configured in my preview.js
like this actions: { argTypesRegex: "^on[A-Z].*" }
and was responsible for overwriting my methods.