This might possibly be how Svelte.js works, but I'm curious if I'm doing something wrong, or if there's a workaround.
If I set compiler option customElement: true
, properties passed to components are not available in the <script>
tag within that component. I use webpack with svelte-loader. Here's a simple example:
// index.html
<my-app foo="testing svelte"></my-app>
<script src="bundle.js"></script>
// script.js (bundled into bundle.js)
import App from './App.svelte';
customElements.define('my-app', App);
// App.svelte
<script>
export let foo;
console.log(foo); // undefined
$: bar = foo.toUpperCase(); // Cannot read property 'toUpperCase' of undefined
$: qux = String(foo).toUpperCase(); // No error, works
</script>
{ foo } // testing svelte - works, as expected
{ qux } // TESTING SVELTE - works, as expected
Also if customElement: true
is not set, and the framework is instantiated with const app = new App(...)
constructor, console.log(foo)
would work, just as $: bar = foo.toUpperCase()
.
Could anyone explain why Svelte works this way? Thanks, cheers!
With custom elements, props are not passed from the constructor, they are only set later on, on the component instance.
What I mean, is that with custom element, it's conceptually like doing this with a standard component:
const app = new App({ target })
app.$set({ foo: 'bar' })
Not that:
const app = new App({ target, props: { foo: 'bar' } })
That's why the value is initially (your console.log
) undefined, but still shows as expected in the markup.
The reason for this is that the init function of a Svelte component (that is, the content of the <script>
tag in your component) is called synchronously from the component constructor (that is, when you do new App(...)
). However, at this point, attributes of the elements are not available (according to this answer).
Either give your prop a default value or check it before using it...
<script>
// default value
export let name = ''
// ... or sanity check
export let other
$: otherName = other != null ? other + name : null
<script>