Closed Florian-Schoenherr closed 4 years ago
Hey, try this:
<script>
import * as S from "svelte-materialify";
const items = [{text: 'Foo', id: 1}, {text: 'Bar', id: 2}];
</script>
<S.MaterialApp>
<S.Select {items}>
<span let:item slot="item">
<S.ListItem value={item.text}>
{item.text}
</S.ListItem>
</span>
Select
</S.Select>
</S.MaterialApp>
In the Svelte-REPL it doesn't work.
"Error: Uncaught (in promise): Cannot read property 'c' of undefined
"
Maybe you fixed something since the last release?
But if it works on your end, I'll try tomorrow in my code. On my end it's pretty late.
And again, thank you!
I think that is a problem with hydrating components, try advanced installation or this template
Ok, it runs fine inside my project. Now when I choose something it shows its index inside the TextField, not the text. (also, maybe that matters: my id is a string)
Updated the example, try again.
Okay, that's how it should look! But it doesn't give back the id when I bind:value on the Select, it gives back the text. I hope I'm not bothering you. Thank you for being so blazingly fast!
The component only outputs the value
of the ListItems to be efficient so you have to do something like:
const id = items.find(x => x.text === value[0]).id
The point of the id is, that there could be texts which are the same. Users could choose between "Foo" and "Foo", which is silly, but then they can choose to show all the details (which changes the text in the Select fields). Maybe my usecase is a little dumb, but I found something that works and shouldn't be less efficient unless the user wants it to.
<script>
import * as S from "svelte-materialify/src";
const items = [{text: 'Foo', id: "1"}, {text: 'Bar', id: "2"}];
let value;
let label = "Items";
$: console.log(value);
const getTextFromId = (val) => typeof val[0] === 'string' ? items.find(i => i.id === val[0]).text : "";
</script>
<S.MaterialApp>
<S.Select {items} bind:value={value} mandatory callback={getTextFromId}>
<span let:item slot="item">
<S.ListItem value={item.id}>
{item.text}
</S.ListItem>
</span>
{label}
</S.Select>
</S.MaterialApp>
inside Select:
const join = (val) => val.join(', ');
export let callback = join;
and
<TextField
{filled}
{outlined}
{solo}
{dense}
{disabled}
value={callback(value)}
{placeholder}
{hint}
readonly>
So this is a 3 lines change and also allows devs to specify what string they want to show after choosing (like I said in the first comment, e.g. don't join value via comma, but maybe hyphens or whatever else)
Nice idea, instead of calling the function callback
, it is better to call it format
, PRs welcome.
have just thrown that together, didn't have an idea for a name :)
First of all, I want to thank you for making this lib, it's really much easier to work with than the other material component libs. Now I have a question, or maybe several, on how the Selects are supposed to be used (in my usecase)
If you use these items, the Select shows the different names inside a ListGroup and after choosing then shows you the chosen value inside a TextField and via binding gives back the value.
My usecase is a little different. I would want my items to have ids, but never show them (or rather, only show them when in details-mode, because otherwise this wouldn't be an issue). Essentially it should work like the normal html-select API, so
option = { text: 'Something', id: 'Invisible' }
<option value={option}>{option.text}</option>
So, these values are shown: Select:
Foo | Bar | Fizz | Buzz
Selected:Foo
And the value-binding should return this to me:
{ name: 'Foo', id: 'someUuid' }
The only workaround I found was to put the id inside the
value:
-part of items, which then shows the uuid as selected. Or I could overwrite some sort of slot, but I really wouldn't know where to start.Maybe it would work to export a callback-function for this right here (one of the TextField-props in Select): This would also be a nice idea because people could use their own delimiter or do whatever else with it.
value={someCallback(value)}
then I could do something like