-
-
Notifications
You must be signed in to change notification settings - Fork 8.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Not able to pass object as attr with stencil.js generated web component #2343
Comments
the issue is likely rooted in the fact that, similar to React, in our new virtual DOM design, we don't differentiate between, (Vue-)props, attributes and domProps (or events) - all are just propertiess on a We handle this for normal DOM Element props/attributes internally during the patch phase, but it seems to fail here for custom elements that rely on objects being passed via properties rather than as attributes (which are always string values). Interested to understand how React et. al. void this. Edit: re-reading your OP got me doubting my understanding, likely because of a lack of familiarity with stencil. You say you expect a stringified object to be passed. Does stencil not use some props to pass objects without the need of being stringified? |
@LinusBorg Thanks for having a look and providing insights!
They don't handle it, I am afraid. From https://custom-elements-everywhere.com/: "React passes all data to Custom Elements in the form of HTML attributes. For primitive data this is fine, but the system breaks down when passing rich data, like objects or arrays. In these instances you end up with stringified values like some-attr="[object Object]" which can't actually be used."
No, that's my mistake. You understood me correctly initially, I think. In my limited understanding of Stencil.js internals, I believe they do not accept stringified objects, but require the framework or vanilla JS implementer to pass it as a prop instead for objects and arrays. From https://custom-elements-everywhere.com/: "By default, Vue passes all data to Custom Elements as attributes. However, Vue also provides syntax to instruct its bindings to use properties instead. To bind to a Custom Element property use :foo.prop="bar"." In the past (Vue 2) we were able to rely on EDIT: From Stencil.js' side, there exists output targets that wrap all web components with framework specific bindings. Angular and React exists, but Vue.js hasn't been implemented yet: https://github.com/ionic-team/stencil-ds-output-targets This wasn't an issue for Stencil.js with Vue 2 though, as |
It seems significant that the "vanilla" custom element doesn't exhibit the same behavior–this would seem to point to a problem in Stencil. I confirmed that a vanilla element seems to work fine here: https://stackblitz.com/edit/vue-rxb2du?file=src%2FApp.vue Notably, it wasn't even necessary to use
|
Thanks @graynorton. Yeah, hoping for an answer from the Stencil.js team too. But also curious as to if this could have to do with state management patterns inside more complex web components, or some similar best practices across web components frameworks, due to custom-elements-everywhere.com and their mention of Vue web component support depending on .prop for handling these type of cases (see quote and reference above). |
@robaxelsen It doesn't look like the tests for custom-elements-everywhere have been updated for Vue 3.0 yet, so I'd guess that the descriptive text hasn't been either. I haven't looked at the Vue source and would be curious what @LinusBorg has to say, but it appears to me that Vue is no longer passing data to custom elements using attributes by default. What's unclear without digging in is whether it's always passing data using properties (which is probably not great), or whether it's doing something fancy based on either the type of data being passed or the existence of a like-named property on the target element. |
I was curious, so played around a bit more. It appears that when binding into a CE, Vue 3.0 will bind to a property if the CE has a property descriptor or a setter for the corresponding name; otherwise, it will bind to an attribute. This seems like a good behavior; it essentially means that Vue will prefer binding to a CE property and fall back to an attribute as needed. @robaxelsen, based on your broken example, it looks to me like Vue's logic to check for the existence of a property is failing for Stencil-created CEs (for whatever reason) and Vue is therefore binding to the attribute instead. Possibly this could be addressed by either Vue or Stencil, but someone will have to dig in and figure out specifically why Vue 3.0 isn't recognizing properties on Stencil CEs. |
Vue just uses Stencil doesn't define the |
Stencil manages the loading of components and by default it does so lazily. |
Stencil has released a new output target |
the .prop doesnt send the data on update... EDIT: it work if I am spreading the object inside { ...myObj } that sounds like a non normal behavior in vue3 at least with reactive |
Closing as 3.2 has re-introduced the |
Version
3.0.0
Reproduction link
https://github.com/robaxelsen/stencil-vue-3-repro
Steps to reproduce
What is expected?
Should return stringified object
[{"id":"id1","label":"Option 1"},{"id":"id2","label":"Option 2"}]
instead of"[object Object],[object Object]"
. The line below is a "hand rolled" web component that does the same successfully. Difference is that the first one is made with Stencil.js.What is actually happening?
Web component renders "[object Object],[object Object]"
instead of the stringified object
[{"id":"id1","label":"Option 1"},{"id":"id2","label":"Option 2"}]`.This example works if we instead use Vue 2 with
object.prop
that since have been deprecated. Does not work with Vue 3.Source code for the live reproducer is here: https://github.com/robaxelsen/stencil-vue-3-repro
Most relevant are these files/folders:
We have not been able to isolate whether this is a Stencil.js or Vue 3 issue, but seems it works with Vue 2 I am posting here first. Will also post issue in Stencil.js repo next, and link to this.
The text was updated successfully, but these errors were encountered: