How can I respond to the _onDrop event in the shell?

I'm working with a SvelteApplication. I can edit the _onDrop method on the sheet but how do I react to it in the svelte shell?
19 Replies
Vauxs
Vauxs3mo ago
One way is to have the shell parse the drop event <div on:drop={func}></div> if you want to still use _onDrop, you'd need to pass the event to the shell, likely through context
geoidesic
geoidesic3mo ago
So I don't want to lose the existing drop functionality in the sheet, I just want to #metoo in the shell
Vauxs
Vauxs3mo ago
make the shell add a function to the window context then, and have _onDrop call that function
geoidesic
geoidesic3mo ago
Actually I'm a bit confused now about what's handling the drop. I don't have any drop handlers so it must be native for foundry Item? const application = getContext("#external").application; has these properties...
"appId"
"options"
"_element"
"_dragDrop"
"_tabs"
"_searchFilters"
"_minimized"
"_state"
"_priorState"
"_scrollPositions"
"appId"
"options"
"_element"
"_dragDrop"
"_tabs"
"_searchFilters"
"_minimized"
"_state"
"_priorState"
"_scrollPositions"
but if I try define my own __dragDrop function on the ItemSheet it doesn't get run Ah.. nvm, I'm being an idiot. There's a drop handler in the shell 🤦🏻‍♂️
Vauxs
Vauxs3mo ago
Lol
geoidesic
geoidesic3mo ago
So the problem I'm having is that it doesn't seem to be possible to access properties on the child from the parent if the child is a dynamic svelete:component E.g.
<script>
import { onMount} from 'svelte';

export let props;


let remoteComponent;
let childRef;

onMount(async () => {
remoteComponent = (await import(`./GrayCard.svelte`)).default;

});
</script>

{#if remoteComponent}
<svelte:component this={remoteComponent} bind:this="{childRef} {...props}><slot /></svelte:component>
{/if}
<script>
import { onMount} from 'svelte';

export let props;


let remoteComponent;
let childRef;

onMount(async () => {
remoteComponent = (await import(`./GrayCard.svelte`)).default;

});
</script>

{#if remoteComponent}
<svelte:component this={remoteComponent} bind:this="{childRef} {...props}><slot /></svelte:component>
{/if}
Neither remoteComponent nor childRef provide a reference, just a proxy object which has none of the child's properties.
Vauxs
Vauxs3mo ago
You are trying to have the child send data to the parent, right?
geoidesic
geoidesic3mo ago
The dlop handler is on the parent. So when that runs, I want to trigger a value to reset in the child
Vauxs
Vauxs3mo ago
I am admittedly once again befuddled by why even doing the whole remote component thing but trying to ignore that for now
geoidesic
geoidesic3mo ago
remote component? Oh.. that's just an example It's a dynamic import and a dynamic child element. Why... because with great power comes great irresponsibility
Vauxs
Vauxs3mo ago
so you want to do something on the child when a parent gets a drop event?
geoidesic
geoidesic3mo ago
yes! that.. parent must direct child, because children are idiots.
Vauxs
Vauxs3mo ago
i will once again tell you to see the context api https://svelte.dev/tutorial/context-api
Svelte tutorial
Context API / setContext and getContext
geoidesic
geoidesic3mo ago
I mean, I know what that is. I'm just not quite seeing how it applies here.
Vauxs
Vauxs3mo ago
you can also export a function from the child component that the parent can call
geoidesic
geoidesic3mo ago
Well I tried the latter... but can't get that to work with a dynamic component Because the dyanmic component doesn't let you bind a reference to it. afaict
Vauxs
Vauxs3mo ago
The parent creates a context. The child adds a function to that context that resets something in itself. The parent calls that function. The child resets itself.
geoidesic
geoidesic3mo ago
Brilliant! Tx. I hadn't quite grokked that context was bi-directional, even though I'd sorta been implicitly using it that way without thinking about it in other contexts.
TyphonJS (Michael)
The context API flows from parent to child components. However instead of putting a function into an object from the child perhaps create a custom store that can be set as a context item in the parent. This way you can potentially reuse this mechanism across any number of child components and not set up a hard association between parent / child. The custom store would look something like: dropTargetStore.js:
import { writable } from 'svelte/store';

function createDropTargetStore() {
const { subscribe, set } = writable(null);

function setDropTarget(target) {
set(target);

setTimeout(() => set(null), 0);
}

return {
subscribe,
set: setDropTarget
};
}

export const dropTarget = createDropTargetStore();
import { writable } from 'svelte/store';

function createDropTargetStore() {
const { subscribe, set } = writable(null);

function setDropTarget(target) {
set(target);

setTimeout(() => set(null), 0);
}

return {
subscribe,
set: setDropTarget
};
}

export const dropTarget = createDropTargetStore();
Parent component:
<script>
import { setContext } from 'svelte';
import { dropTarget } from './dropTargetStore.js';

setContext('dropTarget', dropTarget);

function handleDrop(event) {
// Pass on whatever you want here for the drop target data. You may want to parse things here.
dropTarget.set(event.target);
}
</script>

<div on:drop={handleDrop}>
<!-- component template -->
</div>
<script>
import { setContext } from 'svelte';
import { dropTarget } from './dropTargetStore.js';

setContext('dropTarget', dropTarget);

function handleDrop(event) {
// Pass on whatever you want here for the drop target data. You may want to parse things here.
dropTarget.set(event.target);
}
</script>

<div on:drop={handleDrop}>
<!-- component template -->
</div>
Child component:
<script>
import { getContext } from 'svelte';

const dropTarget = getContext('dropTarget');

$: if ($dropTarget) {
console.log('New drop target:', $dropTarget);
} else {
console.log('Drop target has been reset');
}
</script>

<div>
<!-- component template -->
</div>
<script>
import { getContext } from 'svelte';

const dropTarget = getContext('dropTarget');

$: if ($dropTarget) {
console.log('New drop target:', $dropTarget);
} else {
console.log('Drop target has been reset');
}
</script>

<div>
<!-- component template -->
</div>
Want results from more Discord servers?
Add your server