svelte-material-ui icon indicating copy to clipboard operation
svelte-material-ui copied to clipboard

How to use chip component in an input field?

Open douglasward opened this issue 3 years ago • 1 comments

There is currently in "Input chips" section of the chip component page in the documentation: https://sveltematerialui.com/demo/chips

I assume this means that using the chips inside an input component such as the autocomplete or text field component is possible, e.g. image

but the documentation doesn't seem to show how this is done and I am struggling to work out how to do this.

Is my understanding correct? and if so, could you provide some pointers as to how to do it? I don't mind creating a pull request improving the docs once I understand how it should actually be done.

douglasward avatar Jan 21 '22 19:01 douglasward

<script lang="ts">
    import TextField from '@smui/textfield'
    import Chip, {Set, Text} from '@smui/chips'

    let value = ''
    let input: string[] = []

    const handleSpacePress = (event: KeyboardEvent) => {
        if(event.key === ' ' || event.code === 'Space' || event.code === 'space'){
            if(input.includes(value.trim())){
                alert(`${value} is already a chip`)
                value = ''
                return
            }
            input = [...input, value.trim()]
            value = ''
        }
    }

    const handleDelete = (event: KeyboardEvent) => {
        if(event.key === 'Backspace'){
            if(value === '')
                input.pop()
            input = input
        }
    }
</script>

<TextField bind:value on:keyup={handleSpacePress} on:keyup={handleDelete}>
    <Set style="flex-wrap: nowrap !important;" chips={input} let:chip input>
        <Chip {chip}>
            <Text>{chip}</Text>
        </Chip>
    </Set>
</TextField>

I did find that I wasn't able to get the TrailingAction to show an icon for some reason but I think that might be an issue on my part. TrailingAction does work, but I was getting the word 'cancel' rather than the material icon.

jwsinner avatar Jun 01 '22 16:06 jwsinner

Ok, got it working by making a custom component:

chips-input.svelte

<script lang="ts">
	import TextField from '@smui/textfield';
	import Chip, { Set, Text, TrailingAction } from '@smui/chips';

	export let input: string[] = [];
	export let name = '';
	export let label = '';
	export let placeholder = label;

	let value = ' ';

	const handleKey = (e: CustomEvent) => {
		const event = e as unknown as KeyboardEvent;

		// remove value with backspace
		if (event.key === 'Backspace') {
			if (value === '') input.pop();
		}

		// add value with enter, space, or comma
		if (['Enter', ' ', ','].includes(event.key)) {
			if (input.includes(value.trim())) {
				value = '';
				return;
			}
			if (event.key === ',') {
				value = value.slice(0, -1);
			}
			input.push(value.trim());
			value = '';
		}
		// save new value
		input = input;
	};
</script>

<TextField
	input$name={name}
	type="text"
	variant="outlined"
	class="text-size"
	{placeholder}
	{label}
	bind:value
	on:keyup={handleKey}
>
	<Set class="set" chips={input} let:chip>
		<Chip {chip}>
			<Text>{chip}</Text>
			<TrailingAction icon$class="material-icons white">close</TrailingAction>
		</Chip>
	</Set>
</TextField>

<style global>
	.set {
		flex-wrap: nowrap !important;
	}
        .white {
                color: #fff;
       }
</style>

my-form.svelte

<ChipsInput label="Tags" placeholder="Tags" bind:input={$form.tags} />

Hope this helps someone,

J

jdgamble555 avatar Dec 22 '22 04:12 jdgamble555

I think it is a bug with TrailingAction, so I just styled it color: white.

J

jdgamble555 avatar Dec 22 '22 04:12 jdgamble555