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
| Prop | Type | Description |
|---|---|---|
collectionName | "project" | "user" | "simulation" | "vehicle" | "vehicletype" | "booking" | "node" | "projectmember" | The SGERP collection to search |
onSelectionChange | (values: number[], objects?: any[]) => void | Callback when selection changes. Receives both the ID array and the full objects array |
renderLabel | (item: any) => string | Optional. Function to render item labels. Defaults to name or #id |
placeholder | string | Optional. Button placeholder text. Default: "Select {collectionName}..." |
className | string | Optional. Additional CSS classes |
filters | Record<string, any> | Optional. Additional query filters to apply (e.g., { project_id: 123, simulation_mode: 'template' }) |
disabled | boolean | Optional. Disables the multiselect. Default: false |
language | "en" | "ja" | Optional. Language for UI messages. Defaults to "en" |
value | number[] | 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
valueprop - 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__icontainswhen 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.