SGERP Multiselect

A multi-select dropdown connected to SGERP collections with select all functionality

Project Multi-Select

Select multiple projects using the dropdown. Use "Select All" to select all at once.

Filtered Template Multi-Select

Select a project first, then choose multiple templates from that project.

Prerequisites

This component requires sgerp-frontend-lib to be installed in your project. See the Installation guide for setup instructions.

Dependencies

This component will automatically install:

  • lucide-react - For icons
  • shadcn/ui components: button, popover

Usage

import { SGERPMultiselect } from "@/components/ui/sgerp-multiselect"

export function MyComponent() {
  const [selectedIds, setSelectedIds] = useState<number[]>([])

  return (
    <SGERPMultiselect
      collectionName="project"
      onSelectionChange={setSelectedIds}
      renderLabel={(project) => project.name}
      placeholder="Select projects..."
    />
  )
}

Props

PropTypeDescription
collectionName"project" | "user" | "simulation" | "vehicle" | "vehicletype" | "booking" | "node" | "projectmember"The SGERP collection to search
onSelectionChange(values: number[], objects?: any[]) => voidCallback when selection changes. Receives both the ID array and the full objects array
renderLabel(item: any) => stringOptional. Function to render item labels. Defaults to name or #id
placeholderstringOptional. Button placeholder text. Default: "Select {collectionName}..."
classNamestringOptional. Additional CSS classes
filtersRecord<string, any>Optional. Additional query filters to apply (e.g., { project_id: 123, simulation_mode: 'template' })
disabledbooleanOptional. Disables the multiselect. Default: false
language"en" | "ja"Optional. Language for UI messages. Defaults to "en"
valuenumber[]Optional. Controlled value for the selected item IDs. Makes the component controlled

Features

  • Select All: Checkbox to select/deselect all items at once
  • Individual Selection: Click individual items to toggle selection
  • Auto-selection: Automatically selects the item if only one is available (useful for dependent dropdowns)
  • Search: Built-in search to filter items (300ms debounce)
  • Selected Items Display: Shows selected items as removable chips
  • Loading States: Shows loading indicator while fetching
  • Responsive: Works on all screen sizes
  • Custom Filters: Apply additional query filters for dependent dropdowns
  • Controlled Component: Support external value control via value prop
  • Localization: Supports English and Japanese UI messages

Examples

Basic Usage

<SGERPMultiselect
  collectionName="project"
  onSelectionChange={(ids) => console.log("Selected projects:", ids)}
/>

Custom Label Rendering

<SGERPMultiselect
  collectionName="user"
  onSelectionChange={setUserIds}
  renderLabel={(user) => `${user.first_name} ${user.last_name} (${user.email})`}
  placeholder="Select users..."
/>

With Custom Filters (Auto-selection)

When using dependent dropdowns, if only one item is available, it will be automatically selected:

const [projectId, setProjectId] = useState<number | null>(null);
const [templateIds, setTemplateIds] = useState<number[]>([]);

return (
  <>
    {/* First: Select a project */}
    <SGERPAutocomplete
      collectionName="project"
      onSelectionChange={setProjectId}
      renderLabel={(project) => project.name}
      placeholder="Select a project..."
    />

    {/* Second: Select multiple templates filtered by project */}
    {/* If only one template exists for the project, it will be auto-selected */}
    <SGERPMultiselect
      collectionName="simulation"
      onSelectionChange={setTemplateIds}
      renderLabel={(sim) => sim.name}
      placeholder={projectId ? "Select templates..." : "Select a project first"}
      disabled={!projectId}
      filters={projectId ? { project_id: projectId, simulation_mode: 'template' } : {}}
    />
  </>
);

Using Full Objects from Selection

The callback receives both the ID array and the full objects array:

const [templateIds, setTemplateIds] = useState<number[]>([]);
const [templateNames, setTemplateNames] = useState<string[]>([]);

return (
  <SGERPMultiselect
    collectionName="simulation"
    onSelectionChange={(ids, templates) => {
      setTemplateIds(ids);
      if (templates) {
        setTemplateNames(templates.map(t => t.name));
      }
    }}
    renderLabel={(sim) => sim.name}
    placeholder="Select templates..."
    filters={{ simulation_mode: 'template' }}
  />
);

Controlled Component with Value Prop

Use the value prop to externally control the selected items:

const [selectedProjectIds, setSelectedProjectIds] = useState<number[]>([]);

// Auto-select projects programmatically
useEffect(() => {
  // When there are exactly 2 projects, auto-select them
  if (projects.length === 2) {
    setSelectedProjectIds(projects.map(p => p.id));
  }
}, [projects]);

return (
  <SGERPMultiselect
    collectionName="project"
    value={selectedProjectIds}
    onSelectionChange={(ids) => setSelectedProjectIds(ids)}
    renderLabel={(project) => project.name}
    placeholder="Select projects..."
  />
);

Form Integration

import { SGERPMultiselect } from "@/components/ui/sgerp-multiselect"
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import * as z from "zod"

const formSchema = z.object({
  projectIds: z.array(z.number()).min(1, "At least one project is required"),
})

export function MyForm() {
  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
  })

  return (
    <form onSubmit={form.handleSubmit(onSubmit)}>
      <div>
        <label>Projects</label>
        <SGERPMultiselect
          collectionName="project"
          onSelectionChange={(ids) => form.setValue("projectIds", ids)}
        />
        {form.formState.errors.projectIds && (
          <p className="text-sm text-destructive">
            {form.formState.errors.projectIds.message}
          </p>
        )}
      </div>
    </form>
  )
}

UI Behavior

Select All Checkbox

The "Select All" checkbox has three states:

  • Unchecked: No items selected
  • Checked: All items selected
  • Indeterminate (dash): Some items selected

Clicking it will:

  • Select all items if none or some are selected
  • Deselect all items if all are selected

Removing Items

Selected items appear as chips in the button. Click the X icon on any chip to remove that item from the selection.

API Integration

The component uses the useSGERP() hook to access collections and automatically:

  • Fetches data with a 100-item limit
  • Filters by name__icontains when searching
  • Handles loading and error states
  • Requires an active SGERP connection

Make sure you have set up a connection before using this component. See the Try It Out page for connection setup.