Search code examples
javascriptweb-componentstenciljstsx

stencil js, pass an array as attribute value in custom element


I am looking for a way to pass an array as the value of an attribute of a web component made with stencil js. That's possible?

I'm trying to make something like this works!

index.html

<mv-select options=['one','two','three']></mv-select>

mv-select.tsx

@Component({
  tag: 'mv-select',
  styleUrl: 'mv-select.scss',
  assetsDirs: ['assets'],
    shadow: true
})
export class MvSelect {
  @Element() private element: HTMLElement;
  @Prop() options: string[];

Solution

  • The problem is that HTML attributes can only be strings, not arrays or objects. There are a couple ways to pass an array:

    1. Pass it as a property:
    document.querySelector('mv-select').options = ['one', 'two', 'three'];
    
    1. Pass it as a JSON encoded string attribute:
    <mv-select options='["one", "two", "three"]'></mv-select>
    

    To transform that JSON into an array you can use a @Watch method to update an internal @State property:

    export class MvSelect {
      @Prop() options: string;
      @State() internalOptions: string[];
    
      componentWillLoad() {
        this.parseOptions();
      }
    
      @Watch('options')
      parseOptions() {
        if (this.options) {
          this.innerOptions = JSON.parse(this.options);
        }
      }
    }
    

    This code makes sure that whenever you change options it will be JSON parsed and you can use innerOptions as an array.

    Note that you will have to manually call this.parseOptions() in componentWillLoad because the watchers are not called on initialization.