Skip to content

Pass Object into Web Component Property via Element Attribute #3381

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

Closed
slominskir opened this issue Aug 8, 2019 · 7 comments
Closed

Pass Object into Web Component Property via Element Attribute #3381

slominskir opened this issue Aug 8, 2019 · 7 comments

Comments

@slominskir
Copy link

Currently Svelte doesn't support passing an object into a Web Component property via an attribute. This works if you are using a regular Svelte Component, just not when the compiler is configured to output Web Components (customElement = true).

Worse, the compiler doesn't even warn you about this. So if you take a perfectly functioning Svelte app and flip the switch to output Web Components then it might just break with runtime errors about properties being undefined.

It seems like the compiler could replace attribute assignments to objects with JSON.parse calls, or alternatively replace with bind:this="{component}" and onMount { component.prop = obj; }. Then Svelte code would just work, regardless of if outputting Svelte component vs Web Component. If I'm missing something and this isn't possible, then at least have the compiler warn about this situation.

Here is an Example:

<!-- Label.svelte -->
<script>
    export let config = {};
</script>
<div>{config.text}</div>
<svelte:options tag="test-label"/>
<!-- App.svelte -->
<script>
    import { onMount } from 'svelte';
    import Label from './Label.svelte';

    let config = {text: 'hi'};
    let myLabel;

    onMount(() => {
        myLabel.config = config;
    });
</script>
<Label bind:this="{myLabel}"/>
<svelte:options tag="test-app"/>

In this example, if I instead try to set the property via an attribute it will fail at runtime with undefined property. So for example, this won't work with Web Components:

<Label {config}/>
@slominskir
Copy link
Author

Related: #3237

@MrAmericanMike
Copy link

MrAmericanMike commented Feb 19, 2021

I know this has been open for a long time and I believe it's the same problem I came across. I wonder if this is a good workaround in the meanwhile.

On my index.html

	<hola-svelte></hola-svelte>

	<script>
		let component = document.getElementsByTagName("hola-svelte")[0];
		component.setAttribute("_data", JSON.stringify({ cheer: "Mundo" }));
	</script>

and on my component:

<script>
	export let _data;
	let data = JSON.parse(_data);
	console.log(data);
</script>

<main>
	<h1>¡Hola {data.cheer}!</h1>
</main>

PS: For some reason (I'm not sure why) just doing _data = JSON.parse(_data); doesn't work, so I had to create a data variable, not sure why but I guess it's related to when the component is mounted and the data received.
Also not sure this works correctly once the component is exported to be used somewhere else. Need to do more tests.

@sameerhaque
Copy link

I know this has been open for a long time and I believe it's the same problem I came across. I wonder if this is a good workaround in the meanwhile.

On my index.html

	<hola-svelte></hola-svelte>

	<script>
		let component = document.getElementsByTagName("hola-svelte")[0];
		component.setAttribute("_data", JSON.stringify({ cheer: "Mundo" }));
	</script>

and on my component:

<script>
	export let _data;
	let data = JSON.parse(_data);
	console.log(data);
</script>

<main>
	<h1>¡Hola {data.cheer}!</h1>
</main>

PS: For some reason (I'm not sure why) just doing _data = JSON.parse(_data); doesn't work, so I had to create a data variable, not sure why but I guess it's related to when the component is mounted and the data received.
Also not sure this works correctly once the component is exported to be used somewhere else. Need to do more tests.

This didn't really work for me, Am I missing something?

@MrAmericanMike
Copy link

MrAmericanMike commented Mar 2, 2021

This didn't really work for me, Am I missing something?

Try this repo. Don't follow the instructions on the README, that's from the template.

https://github.com/MrAmericanMike/svelte-component

once cloned, npm install then npm run build

Then open index.html on public with Live Server (Or any other server) Or you could just open directly on browser. Just check console for errors, in which case you may need to adjust the route to the .js files.

Let me know how it goes.

PS: That example even handles default values.

@stale
Copy link

stale bot commented Jun 26, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale-bot label Jun 26, 2021
@stale stale bot removed the stale-bot label Jun 26, 2021
@stale stale bot removed the stale-bot label Jun 27, 2021
@stale
Copy link

stale bot commented Dec 27, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@dummdidumm
Copy link
Member

Closing as duplicate of #3594 - the underlying issue is the same, that it's currently "all or nothing", and once customElement: true is set, all inner component usages have to be custom elements, too.

@dummdidumm dummdidumm closed this as not planned Won't fix, can't repro, duplicate, stale Mar 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants