Using Objects/Arrays as Props in Stencil Components

Gil Fink
2 min readOct 10, 2017

A few questions were asked in Stencil Slack channel about how to set objects/arrays as props in Stencil components.
This short post should answer those questions.

Using Objects/Arrays as Props within Another Framework

If you are using a Stencil components in a framework such as Angular or React, their usage is straight forward. You just need to use the framework syntax and bind the component attributes to the relevant object/array.

Let’s take a look at an Angular example:

<st-login [forgotPasswordUrl]="/forgot"
(loginShouldOccur)="doLogin($event)"
>
</st-login>

st-login is a Stencil component and you can find it’s implementation here. In the code example I just bind the forgotPasswordUrl Prop using brackets. I also bind the loginShouldOccur event I exposed in the component. In the same way you could have passed a object/an array and the framework will handle the binding for you.

Using Objects/Arrays as Props without a Framework

The problem starts when you use a Stencil component in raw HTML and without a framework. The normal behavior of HTML attributes is to treat their values as strings. When you set an attribute to a object/array, it will be treated as a string and therefore it might be confusing to developers who come to Stencil with framework background. For example, in the following code the data attribute is expecting an array on Stencil component side but will get a string representation of the array instead:

<my-comp data='[{"name":"Stencil","url":"www.stenciljs.com"},{"name":"Google","url":"www.google.com"}]'></my-comp>

So, how we can fix the problem?

  • The first option is just to use JavaScript to set the Props. For example, the following code will set the data Prop to the relevant array:
var cmp = document.querySelector('my-comp');
cmp.data = arr; // arr is the array you are want to pass
  • The second option is to use property change detection inside the Stencil component and use JSON.parse to handle the object/array deserialization. We can use Watch() decorator to intercept the attribute change and then set an inner member inside the component to the parsed object/array. This option adds overhead and complexity to your component and is error prone, so I prefer to use the first option. The following code can be a simple implementation of this option:
@Watch('data')
dataDidChangeHandler(newValue: boolean) {
this.innerData = JSON.parse(newValue);
}

Summary

Setting a Stencil component attributes without a framework has a small caveat. In this post I explained the caveat and the workarounds that you can use.

--

--

Gil Fink

Hardcore web developer, @sparXys CEO, Google Web Technologies GDE, Pro SPA Development co-author, husband, dad and a geek.