Say I render the following Dialog:
let dialog;
<MyDialog bind:this={dialog}/>
I want to position this dialog (using afterUpdate
lifecycle function I guess). However, dialog
is not a dom element. When I log it, it will look something like:
MyDialog {$$: {…}, left: 785, $set: ƒ, $capture_state: ƒ, $inject_state: ƒ}
$$: {fragment: {…}, ctx: Array(1), props: {…}, update: ƒ, not_equal: ƒ, …}
$capture_state: () => {…}
$inject_state: $$props => {…}
$set: $$props => {…}
someExportedProp: (...)
__proto__: SvelteComponentDev
How can I access its dom in order to position it?
MyDialog
is not a DOM element, it is a Svelte component. And so, it's what you get when you bind:this
on it: a Svelte component.
You only get a DOM element when binding to an actual element:
<div bind:this={el} />
If you need access to the DOM of MyDialog
from its consumer (parent) component, you need to proxy it from the MyDialog
component.
MyDialog.svelte
<script>
export let el
</script>
<div class="dialog" bind:this={el}>
<slot />
</div>
App.svelte
<script>
import MyDialog from './MyDialog.svelte'
let dialog
$: console.log(dialog) // here, DOM element!
</script>
<MyDialog bind:el={dialog}>
Hello!
</MyDialog>
That being said, I would think twice before leaking DOM elements outside of component. It kinda breaks encapsulation, which often ends up complicating your life... Maybe you can think of a better solution to control your dialog position without giving direct access to the innards of the component to the consumer?
EDIT
To move with props...
Props are "reactive", their value is automatically reflected in the DOM by the framework, so you don't need to run a function to move things. You can just declare what you want. This is the preferred style with these declarative frameworks.
<script>
export let top
export let left
$: style = `top: ${top}px; left: ${left}px`
</script>
<div class="dialog" {style}>
<slot />
</div>
If you need too, you can still run some code when props change (imperatively) with reactive blocks:
<script>
export let top
export let left
let el
// reactive block will rerun each time el, top, or left changes
$: if (el) {
el.style.top = top + 'px'
el.style.left = left + 'px'
}
</script>
<div class="dialog" bind:this={el}>
<slot />
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With