简体   繁体   中英

Storybook web-components: sending array as component property

I'm using Storybook 6.5.9 to render web components (made with Stencil). I have several of them working correctly but now I'm creating a story for a new component that can receive a property that is an array of objects.

The component would be something like this:

import {Component, Host, h, Prop} from '@stencil/core';

@Component({
  tag: 'test-component',
})

export class TestComponent {
  /**
   * Array of options for the group.
   */
  @Prop() items?: String[] = [];

  render() {
    return (
      <Host>
        {
          this.items.map(item => (
            <h1>{item}</h1>
          ))
        }
      </Host>
    )
  }
}
      

And this is the story:

import { Story, Meta } from '@storybook/html';

export default {
  title: 'Components/TestComponent',
  parameters: {
    options: {
      showPanel: true
    },
  }
} as Meta;

const Template: Story = (args) => {
  return `
    <test-component items="${['some', 'thing']}">
    </test-component>
  `;
};

export const TestComponent: Story = Template.bind({});

I have tried setting the items property to a string but the component never gets anything, it's always an empty array.

I'm not getting any errors either in the console. I'm definitely doing something wrong but I don't know what it is... I've been using several other data types for those properties (boolean, string, numbers...) but this is the first time I'm using objects/arrays and I'm not able to get it to work.

Any help will be highly appreciate it.

Thanks!

Properties are passed in as strings in HTML.

Use JSON.parse(this.items) in your render() method in case this.items is not an array :

import { Component, Host, h, Prop } from '@stencil/core';

@Component({
  tag: 'my-component',
})
export class MyComponent {
  /**
   * Array of options for the group.
   */
  @Prop() items?: string | string[] = '';

  render() {
    return (
      <Host>
        {(Array.isArray(this.items) ? this.items : JSON.parse(this.items)).map(item => (
          <h1>{item}</h1>
        ))}
      </Host>
    );
  }
}

For that to work, you need to pass in your items as valid JSON, meaning you have to use single attribute quotes and double quotes for the "strings" in the "array":

const Template: Story = (args) => `
    <test-component items='${["some", "thing"]}'>
    </test-component>
`;

If you are receiving [object Object] in your component, try to stringify your prop value before passing:

const Template: Story = (args) => `
    <test-component items='${JSON.stringify(["some", "thing"])}'>
    </test-component>
`;

You can not set arrays or objects as properties via HTML (only in JSX/TSX). You have two options:

  1. pass them as a JSON string and parse them back into an array/object; you'd basically have to type them as a string in your component, and then cast the type after parsing them
  2. set the property via a script; there's two options, depending on whether or not the option is required or not.
<test-component></test-component>

<script>
  document.querySelector("test-component").items = ["foo"]
</script>

or if the prop is required:

<script>
  const testComponent = document.createElement("test-component")

  testComponent.items = ["foo"]

  document.body.appendChild(testComponent)
</script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM