@storybook/angular
Version:
Storybook for Angular: Develop Angular components in isolation with hot reloading.
59 lines (58 loc) • 2.57 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.argsToTemplate = argsToTemplate;
const ComputesTemplateFromComponent_1 = require("./angular-beta/ComputesTemplateFromComponent");
/**
* Converts an object of arguments to a string of property and event bindings and excludes undefined
* values. Why? Because Angular treats undefined values in property bindings as an actual value and
* does not apply the default value of the property as soon as the binding is set. This feels
* counter-intuitive and is a common source of bugs in stories.
*
* @example
*
* ```ts
* // component.ts
* ㅤ@Component({ selector: 'example' })
* export class ExampleComponent {
* ㅤ@Input() input1: string = 'Default Input1';
* ㅤ@Input() input2: string = 'Default Input2';
* ㅤ@Output() click = new EventEmitter();
* }
*
* // component.stories.ts
* import { argsToTemplate } from '@storybook/angular';
* export const Input1: Story = {
* render: (args) => ({
* props: args,
* // Problem1: <example [input1]="input1" [input2]="input2" (click)="click($event)"></example>
* // This will set input2 to undefined and the internal default value will not be used.
* // Problem2: <example [input1]="input1" (click)="click($event)"></example>
* // The default value of input2 will be used, but it is not overridable by the user via controls.
* // Solution: Now the controls will be applicable to both input1 and input2, and the default values will be used if the user does not override them.
* template: `<example ${argsToTemplate(args)}"></example>`,
* }),
* args: {
* // In this Story, we want to set the input1 property, and the internal default property of input2 should be used.
* input1: 'Input 1',
* click: { action: 'clicked' },
* },
* };
* ```
*/
function argsToTemplate(args, options = {}) {
const includeSet = options.include ? new Set(options.include) : null;
const excludeSet = options.exclude ? new Set(options.exclude) : null;
return Object.entries(args)
.filter(([key]) => args[key] !== undefined)
.filter(([key]) => {
if (includeSet)
return includeSet.has(key);
if (excludeSet)
return !excludeSet.has(key);
return true;
})
.map(([key, value]) => typeof value === 'function'
? `(${key})="${(0, ComputesTemplateFromComponent_1.formatPropInTemplate)(key)}($event)"`
: `[${key}]="${(0, ComputesTemplateFromComponent_1.formatPropInTemplate)(key)}"`)
.join(' ');
}
;