InputChip component not updating when selecting value from AutoComplete component Svelte

141 Views Asked by At

I'm trying to build a component which allows a user the ability to search through categories using the autocomplete and have it appear as a chip within the Skeleton UI InputChip component. I am also trying to utilise the AutoComplete component. My issue is when I try and select a category from the AutoComplete it doesn't update the chips on the UI.

<script lang="ts">
  import { page } from "$app/stores";
  import { createQuery } from "@tanstack/svelte-query";
  import LoadingSpinner from "$lib/components/ui/LoadingSpinner.svelte";
  import {
    toastStore,
    InputChip,
    Autocomplete,
    type AutocompleteOption
  } from "@skeletonlabs/skeleton";

  const { supabase } = $page.data;

  export let selectedCategoryIds: string[] = [];
  export let subcatPaths: string[] = [];

  let whitelist: string[] = [];
  let selectedCategoryLabels: string[] = [];
  let selectedCategoryChips: string[] = [];
  let categoryOptions: AutocompleteOption[] = [];
  let inputChipCategory: string;

  $: categories = createQuery({
    queryKey: ["categories"],
    queryFn: async () => {
      const { data: cats, error } = await supabase.from("categories").select();

      if (error) throw error;

      return cats.map(
        (category) =>
          ({
            label: category.label,
            value: category.id,
            keywords: category.keywords
          } as AutocompleteOption)
      );
    },
    onSuccess: (data) => {
      categoryOptions = data;
      whitelist = data.map((category) => category.label);
    },
    onError: (err) => {
      console.log(err);
      toastStore.trigger({
        message: "Error fetching categories.",
        background: "variant-filled-error"
      });
    }
  });

  function onCategorySelect(event: CustomEvent<AutocompleteOption>) {
    if (
      !selectedCategoryIds.some((category) => category === event.detail.value)
    ) {
      selectedCategoryIds = [
        ...selectedCategoryIds,
        event.detail.value as string
      ];

      selectedCategoryLabels = [
        ...selectedCategoryLabels,
        event.detail.label as string
      ];
    }
  }

  $: selectedCategoryChips = selectedCategoryLabels;
</script>

<div class="label">
  <span>Categories</span>
  <InputChip
    {whitelist}
    allowUpperCase
    bind:input={inputChipCategory}
    bind:value={selectedCategoryChips}
    name="chips"
    placeholder="Enter 3 categories..."
    chips="variant-filled-primary"
    min="3"
  />
</div>

<div
  class="card w-full max-h-48 {$categories.isLoading
    ? 'p-4'
    : 'p-1'} overflow-y-auto"
>
  {#if $categories.isLoading}
    <center>
      <LoadingSpinner />
    </center>
  {:else if $categories.isSuccess}
    <Autocomplete
      options={categoryOptions}
      denylist={selectedCategoryIds}
      bind:input={inputChipCategory}
      on:selection={onCategorySelect}
    />
  {/if}
</div>

I know for sure that the selectedCategoryChips string array is being updated and you might be wondering why I'm not using the selectedCategoryLabels array instead, I was trying to take reference from this but it didn't work unfortunately.

If anyone can help out that would be great :)

1

There are 1 best solutions below

0
On

i guess you are trying to do something like this

skeleton-ui input chip

if that's the case you could adapt it like in the skeleton-ui documentation

js

let inputChip = '';
let inputChipList: string[] = ['vanilla', 'chocolate'];

html

<InputChip bind:input={inputChip} bind:value={inputChipList} name="chips" />
<div class="card w-full max-w-sm max-h-48 p-4 overflow-y-auto" tabindex="-1">
    <Autocomplete
        bind:input={inputChip}
        options={flavorOptions}
        denylist={inputChipList}
        on:selection={onInputChipSelect}
    />
</div>