-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Dynamic slot names #6493
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
Comments
I made it work like this for now: ...
{:else if col.type === 'custom'}
<slot col={col} value={row.data[col.key]}></slot>
{/if}
... And inside the component: <DataTable bind:cols bind:data
let:col
let:value>
<!-- Could contain a button, icon div or anything we'd like -->
{#if col.key === 'custom1'}
<span>
<button
on:click={(e) => {
e.stopPropagation();
console.log('asdasd')
}}
>TEST</button>
</span>
{:else if col.key === 'custom2'}
{#each value as v}
<p>{v}</p>
{/each}
{:else if col.key === 'bool'}
{#if value}
TRUE - {value} - {col.title}
{:else}
FALSE - {value}
{/if}
{/if}
</DataTable> |
I have this problem too, I build custom DataTable too 🤣 Btw thanks @csangonzo for the workaround, I like your idea. But it's still hard to use. Still far from ideal dynamic named slot. Hope this feature coming to svelte soon. This framework is awesome and very fast |
I have this problem too, I build custom DataTable too 🤣 |
this problem is pretty common , if you build tab ui |
I wonder if there is a common way to deal with this case. Is this the reason at compile time? 😭 |
an another method maybe helps you https://github.com/yus-ham/blangko/blob/db7e475c704454d418e1f6e7331452932e6a5b6d/src_front/pages/posyandu/index.svelte#L13-L38 |
In addition to the datatable example, I'd like to add another use case regarding advanced i18n interpolation. For example, if we want to create something like this <Trans message={t("user-click")}>
<FancyLookingNumber slot="count">{2}</FancyLookingNumber>
</Trans> In English, |
My workaround involves passing an array prop that gives the names of the slots, pregenerating some named slots with numbers, binding the contents to a variable, and then just setting the children of the element once my translation is looked up. Here's what it looks like: <script>
import { onMount, onDestroy } from "svelte";
import App from "../app.mjs";
import translate from "../translate.mjs";
const unregister = [];
export let opts = {};
export let key;
export let slotMapping = [];
let slotContents = {};
let language;
let contentElement;
function render() {
if (language) {
const { result, usedFallback } = translate(
language,
key,
opts,
false
);
let newContents;
if (usedFallback) {
newContents = `<span style="background: red" title="NO TRANSLATION KEY">${result}</span>`;
} else {
newContents = result;
}
newContents = newContents.split(/(%\w+%)/g);
for (const [index, value] of newContents.entries()) {
if (value.startsWith("%")) {
const slotName = value.slice(1, -1);
const slotId = "item" + slotMapping.indexOf(slotName);
newContents[index] = slotContents[slotId];
} else {
const span = document.createElement("span");
span.innerHTML = value;
newContents[index] = span;
}
}
if (slotMapping.length > 0) {
console.debug(
"[LocalizedText] localized with slots:",
key,
slotMapping,
result,
newContents
);
}
contentElement?.replaceChildren(...newContents);
} else {
contentElement?.replaceChildren(...[key]);
}
}
onMount(() => {
unregister.push(
App.on("language", (l) => {
language = l;
render();
})
);
});
onDestroy(() => {
for (const un of unregister) {
try {
App.off(un[0], un[1]);
} catch (ignored) {}
}
});
// Rerender on change
$: key, render();
$: opts, render();
</script>
<div style="display: none;">
<!-- We need 10 of these -->
<span bind:this={slotContents.item0}><slot name="0" /></span>
<span bind:this={slotContents.item1}><slot name="1" /></span>
<span bind:this={slotContents.item2}><slot name="2" /></span>
<span bind:this={slotContents.item3}><slot name="3" /></span>
<span bind:this={slotContents.item4}><slot name="4" /></span>
<span bind:this={slotContents.item5}><slot name="5" /></span>
<span bind:this={slotContents.item6}><slot name="6" /></span>
<span bind:this={slotContents.item7}><slot name="7" /></span>
<span bind:this={slotContents.item8}><slot name="8" /></span>
<span bind:this={slotContents.item9}><slot name="9" /></span>
</div>
<span bind:this={contentElement} /> Example usage (abridged): <LocalizedText key="chatbot_manager.commands.format.{command.type}" slotMapping={["platform", "action", "action_target", "message"]}>
<div class="select" slot="0">
<select bind:value={command.platform}>
{#each PLATFORMS as platform}
<option value={platform[0]}>{platform[1]}</option>
{/each}
</select>
</div>
<div class="select" slot="1">
<select bind:value={command.type}>
<option value="COMMAND">
<LocalizedText key="chatbot_manager.commands.runs" />
</option>
<option value="CONTAINS">
<LocalizedText key="chatbot_manager.commands.mentions" />
</option>
</select>
</div>
<span slot="2">
<input class="input" type="text" bind:value={command.trigger} style="width: 200px" />
</span>
<span slot="3">
<br />
<textarea class="textarea" bind:value={command.response} rows={2} />
</span>
</LocalizedText> My lang file: ( {
"chatbot_manager.commands.format.COMMAND": "When someone from %platform% %action% !%action_target%, send %message%",
"chatbot_manager.commands.format.CONTAINS": "When someone from %platform% %action% [generic.leftquote]%action_target%[generic.rightquote], reply with %message%"
} Obviously, this is pretty dirty but it works. My ideal would look like: <script>
// ... lookup translation, yada yada
</script>
{#if contents}
{#each contents as item}
{#if item.startsWith('%')}
<slot name={item.slice(1, -1) /* trim off the %'s */} />
{:else}
{@html item}
{/if}
{/each}
{:else}
{key} <!-- Fallback -->
{/if} |
Would love to see this feature as well! |
Yes, please. We absolutely need this! |
@Conduitry |
Is there any update on this feature? |
Just coming here to add my voice to this, I was halfway through recreating this exact solution for my own translation project and ran into this limitation. I'll likely go with @e3nder's suggestion of having a number of "dummy" slots but it's a bit disappointing that this isn't possible! |
My another solution is not using slot, but using |
Good solution as well, though I personally prefer my data and text to be in the markup and not in the JS. Still, any solution is better than none :^) |
For those who are building custom datatable like what I did, my solution is as below:
This works in my situation, hope it will be helpful. |
Any updates on the issue? |
I do not know |
Is there an update when will this be released? |
#8535 |
This is the main issue with svelte I'm having, and it the absence of this feature keeps hindering my development. I want to strongly voice my support for this! |
Describe the problem
I'm building an extensible data table component, it works pretty well now, but the only thing missing is slots with dynamic names.
So the way the table works is you can set column definitions and the data, the column definitions contain the key that matches the key in the data e.g.
key: "name"
and if there's aname: "something"
in the data, the name column has values. Right now I have a button, icon and other actiontypes
available so when the dev. sets a column to abutton
type it shows a button, so far so good. The only problem with this is that only my predefined button styles are available and what would be a great solution is to define the column type ascustom
and when I set the key totestColumn
it would look for a slot namedtestColumn
, so in the table component:and I'd pass the matching slot outside of the component:
( There was an issue regarding this, but it was submitted as a bug rather than a feature request and lacked detailed explanation: #5859 )
Describe the proposed solution
It would be really awesome if we could do something like this in svelte ( if I'm correct vue has something like this: https://vuejs.org/v2/guide/components-slots.html#Dynamic-Slot-Names ), it would open up whole new possibilities for svelte components.
Alternatives considered
It doesn't necessary have to work with slots like I mentioned, I'm open to any 'svelter' solution as well.
Importance
would make my life easier
The text was updated successfully, but these errors were encountered: