ShadCN UI 组合框,如何从中传递数据?

问题描述 投票:0回答:1

我有一个带有 nextjs 的组件组合框 shadcn,组件放入表单中,提交时如何在 console.log 中看到 id='student' name='student' 这样的值

这是我的源代码

"use client"

import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import * as React from 'react'

import { Check, ChevronsUpDown } from "lucide-react"

import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from "@/components/ui/command"
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover"
import SubmitButtonForm from '../../components/submit-form-button'
import { Airplane } from '@prisma/client'
import { useFormState } from 'react-dom'
import { saveFlight } from '../lib/action'
import { ActionResult } from '@/app/dashboard/(auth)/signin/form/action'

interface FormFlightProps {
  airplanes: Airplane[]
}

const initialFormState: ActionResult = {
  errorTitle: null,
  errorDesc: []
}

export default function FormFlight({ airplanes }: FormFlightProps) {

  // console.log(airplanes)

  // const frameworks = [
  //   {
  //     planeId: 1,
  //     value: "next.js",
  //     label: "Next.js",
  //   },
  //   {
  //     planeId: 2,
  //     value: "sveltekit",
  //     label: "SvelteKit",
  //   },
  //   {
  //     planeId: 3,
  //     value: "nuxt.js",
  //     label: "Nuxt.js",
  //   },
  //   {
  //     planeId: 4,
  //     value: "remix",
  //     label: "Remix",
  //   },
  //   {
  //     planeId: 5,
  //     value: "astro",
  //     label: "Astro",
  //   },
  // ]

  const [state, formAction] = useFormState(saveFlight, initialFormState)

  function ComboboxDemo() {
    const [open, setOpen] = React.useState(false)
    const [value, setValue] = React.useState("")

    return (
      <Popover open={open} onOpenChange={setOpen}>
        <PopoverTrigger asChild>
          <Button
            variant="outline"
            role="combobox"
            aria-expanded={open}
            className="w-[100%] justify-between mt-8"
          >
            {value
              ? airplanes.find((airplane) => airplane.name === value)?.name
              : "Pilih Pesawat..."}
            <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
          </Button>
        </PopoverTrigger>
        <PopoverContent className="w-[250px] md:w-[370px] lg:w-[640px] p-0">
          <Command>
            <CommandInput placeholder="Cari Pesawat/Penerbangan..." />
            <CommandList>
              <CommandEmpty>Pesawat/Penerbangan tidak ditemukan.</CommandEmpty>
              <CommandGroup>
                {airplanes.map((airplane) => (
                  <CommandItem
                    key={airplane.id}
                    value={airplane.name}
                    onSelect={(currentValue) => {
                      setValue(currentValue === value ? "" : currentValue)
                      setOpen(false)

                    }}
                  >
                    <Check
                      className={cn(
                        "mr-2 h-4 w-4",
                        value === airplane.id ? "opacity-100" : "opacity-0"
                      )}
                    />
                    {airplane.name}
                  </CommandItem>
                ))}
              </CommandGroup>
            </CommandList>
          </Command>
        </PopoverContent>
      </Popover>
    )
  }

  return (
    <form action={formAction} className='space-y-6'>
      <div className='grid grid-cols-2 gap-4'>
        <div className='space-y-2'>
          <Label htmlFor="planeId">Pilih Pesawat</Label>
          <ComboboxDemo />
          {/* <Input
            // placeholder="Harga Tiket..."
            type='hidden'
            name="planeId"
            id="planeId"
            value={'test'}
            required
          /> */}
        </div>

        <div className="space-y-2">
          <Label htmlFor="price">Harga Tiket</Label>
          <Input
            placeholder="Harga Tiket..."
            name="price"
            id="price"
            type='number'
            min={0}
            required
          />
          <span className="text-xs text-gray-900">
            *Kelas Bisnis ++ Rp 500.000, Kelas First ++ Rp 750.000*
          </span>
        </div>
      </div>
      <div className="grid grid-cols-3 gap-4">
        <div className="space-y-2">
          <Label htmlFor="departureCity">Kota Keberangkatan</Label>
          <Input
            placeholder="Kota Keberangkatan..."
            name="departureCity"
            id="departureCity"
            required
          />
        </div>
        <div className="space-y-2">
          <Label htmlFor="departureDate">Tanggal Keberangkatan</Label>
          <Input
            type='datetime-local'
            placeholder="Tanggal Keberangkatan..."
            name="departureDate"
            id="departureDate"
            className='block'
            required
          />
        </div>
        <div className="space-y-2">
          <Label htmlFor="departureCityCode">Kode Kota</Label>
          <Input
            placeholder="Kode Kota..."
            name="departureCityCode"
            id="departureCityCode"
            required
          />
        </div>
      </div>
      <div className="grid grid-cols-3 gap-4">
        <div className="space-y-2">
          <Label htmlFor="destinationCity">Kota Tujuan</Label>
          <Input
            placeholder="Kota Tujuan..."
            name="destinationCity"
            id="destinationCity"
            required
          />
        </div>
        <div className="space-y-2">
          <Label htmlFor="arrivalDate">Tanggal Tiba</Label>
          <Input
            type='datetime-local'
            placeholder="Tanggal Tiba..."
            name="arrivalDate"
            id="arrivalDate"
            className='block'
            required
          />
        </div>
        <div className="space-y-2">
          <Label htmlFor="destinationCityCode">Kode Kota</Label>
          <Input
            placeholder="Kode Kota..."
            name="destinationCityCode"
            id="destinationCityCode"
            required
          />
        </div>
      </div>

      <SubmitButtonForm />
    </form>
  )
}

我希望当我提交后console.log formData存在时,如下所示

FormData {
  '$ACTION_REF_2': '',
  '$ACTION_2:0': '{"id":"eee2f8c376832dd5ff345bf9d7d9b86748644191","bound":"$@1"}',
  '$ACTION_2:1': '[{"errorTitle":null,"errorDesc":[]}]',
  '$ACTION_KEY': 'k3995036715',
  **planeId: 'test',** <---- like here
  price: '1234567',
  departureCity: 'Bandung',
  departureDate: '2024-09-15T16:28',
  departureCityCode: 'BDG',
  destinationCity: 'Jakarta',
  arrivalDate: '2024-09-15T22:28',
  destinationCityCode: 'JKT'
}

我尝试将名称和 id 添加到 Item 命令中,但是当我查看 console.log 时,它没有出现

reactjs react-native combobox nextjs14 shadcnui
1个回答
0
投票

您需要正确管理状态并确保此状态反映在将包含在表单数据中的隐藏输入字段中。

您需要在表单中添加一个隐藏的输入字段以捕获在 ComboboxDemo 组件中选择的值。每当选择更改时,应更新此字段。当在 ComboboxDemo 中进行选择时,隐藏输入字段的值会相应更新。

    "use client"

import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import * as React from 'react'
import { Check, ChevronsUpDown } from "lucide-react"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from "@/components/ui/command"
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover"
import SubmitButtonForm from '../../components/submit-form-button'
import { Airplane } from '@prisma/client'
import { useFormState } from 'react-dom'
import { saveFlight } from '../lib/action'
import { ActionResult } from '@/app/dashboard/(auth)/signin/form/action'

interface FormFlightProps {
  airplanes: Airplane[]
}

const initialFormState: ActionResult = {
  errorTitle: null,
  errorDesc: []
}

export default function FormFlight({ airplanes }: FormFlightProps) {

  const [state, formAction] = useFormState(saveFlight, initialFormState)

  function ComboboxDemo() {
    const [open, setOpen] = React.useState(false)
    const [value, setValue] = React.useState<string>("")

    // Update the hidden input field with the selected value
    React.useEffect(() => {
      const hiddenInput = document.getElementById('planeId') as HTMLInputElement
      if (hiddenInput) {
        hiddenInput.value = value
      }
    }, [value])

    return (
      <Popover open={open} onOpenChange={setOpen}>
        <PopoverTrigger asChild>
          <Button
            variant="outline"
            role="combobox"
            aria-expanded={open}
            className="w-[100%] justify-between mt-8"
          >
            {value
              ? airplanes.find((airplane) => airplane.name === value)?.name
              : "Pilih Pesawat..."}
            <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
          </Button>
        </PopoverTrigger>
        <PopoverContent className="w-[250px] md:w-[370px] lg:w-[640px] p-0">
          <Command>
            <CommandInput placeholder="Cari Pesawat/Penerbangan..." />
            <CommandList>
              <CommandEmpty>Pesawat/Penerbangan tidak ditemukan.</CommandEmpty>
              <CommandGroup>
                {airplanes.map((airplane) => (
                  <CommandItem
                    key={airplane.id}
                    value={airplane.name}
                    onSelect={(currentValue) => {
                      setValue(currentValue === value ? "" : currentValue)
                      setOpen(false)
                    }}
                  >
                    <Check
                      className={cn(
                        "mr-2 h-4 w-4",
                        value === airplane.name ? "opacity-100" : "opacity-0"
                      )}
                    />
                    {airplane.name}
                  </CommandItem>
                ))}
              </CommandGroup>
            </CommandList>
          </Command>
        </PopoverContent>
      </Popover>
    )
  }

  return (
    <form action={formAction} className='space-y-6'>
      <div className='grid grid-cols-2 gap-4'>
        <div className='space-y-2'>
          <Label htmlFor="planeId">Pilih Pesawat</Label>
          <ComboboxDemo />
          <Input
            type='hidden'
            name="planeId"
            id="planeId"
            required
          />
        </div>

        <div className="space-y-2">
          <Label htmlFor="price">Harga Tiket</Label>
          <Input
            placeholder="Harga Tiket..."
            name="price"
            id="price"
            type='number'
            min={0}
            required
          />
          <span className="text-xs text-gray-900">
            *Kelas Bisnis ++ Rp 500.000, Kelas First ++ Rp 750.000*
          </span>
        </div>
      </div>
      <div className="grid grid-cols-3 gap-4">
        <div className="space-y-2">
          <Label htmlFor="departureCity">Kota Keberangkatan</Label>
          <Input
            placeholder="Kota Keberangkatan..."
            name="departureCity"
            id="departureCity"
            required
          />
        </div>
        <div className="space-y-2">
          <Label htmlFor="departureDate">Tanggal Keberangkatan</Label>
          <Input
            type='datetime-local'
            placeholder="Tanggal Keberangkatan..."
            name="departureDate"
            id="departureDate"
            className='block'
            required
          />
        </div>
        <div className="space-y-2">
          <Label htmlFor="departureCityCode">Kode Kota</Label>
          <Input
            placeholder="Kode Kota..."
            name="departureCityCode"
            id="departureCityCode"
            required
          />
        </div>
      </div>
      <div className="grid grid-cols-3 gap-4">
        <div className="space-y-2">
          <Label htmlFor="destinationCity">Kota Tujuan</Label>
          <Input
            placeholder="Kota Tujuan..."
            name="destinationCity"
            id="destinationCity"
            required
          />
        </div>
        <div className="space-y-2">
          <Label htmlFor="arrivalDate">Tanggal Tiba</Label>
          <Input
            type='datetime-local'
            placeholder="Tanggal Tiba..."
            name="arrivalDate"
            id="arrivalDate"
            className='block'
            required
          />
        </div>
        <div className="space-y-2">
          <Label htmlFor="destinationCityCode">Kode Kota</Label>
          <Input
            placeholder="Kode Kota..."
            name="destinationCityCode"
            id="destinationCityCode"
            required
          />
        </div>
      </div>

      <SubmitButtonForm />
    </form>
  )
}
© www.soinside.com 2019 - 2024. All rights reserved.