Driver Table
Pre-configured table component for displaying simulation drivers
Live Example
Drivers Table
Browse drivers with names and external IDs. Click a row to see the data.
DriverTable
A ready-to-use table component for displaying driver information with filtering and sorting capabilities.
Usage
Display drivers in a table with automatic dependent API calls for user and project membership data.
import { useSGERP } from 'sgerp-frontend-lib';
import { DriverTable } from '@/components/sgerp/tables/driver-table';
function MyComponent() {
const api = useSGERP();
return (
<DriverTable
collection={api?.collections.driver ?? null}
onRowClick={(row) => console.log('Clicked:', row)}
/>
);
}
Features
- Columns: Name, Login (username), Organization, Access to Projects
- Filters: First Name (text search)
- Default Sort:
-created_at(newest first) - Page Size: 20 items per page
- Dependent API Calls: Automatically fetches related user and project membership data
- Batched Name Lookups: Organization and project names are fetched in batched requests for optimal performance
Props
| Prop | Type | Required | Description |
|---|---|---|---|
collection | DriverCollection | null | Yes | The driver collection to display |
columns | ColumnDef<Driver>[] | No | Custom column definitions (overrides defaults) |
filters | FilterDef<Driver>[] | No | Custom filter definitions (overrides defaults) |
initialOrderBy | string | No | Initial sort field (default: -created_at) |
pageSize | number | No | Items per page (default: 20) |
onRowClick | (row: Driver) => void | No | Callback when a row is clicked |
hideColumns | string[] | No | Array of column keys to hide |
Column Details
Name
Displays the driver's first name. Sortable by first_name.
Login
Shows the username from the associated user account. Fetched automatically via dependent API call. Returns "-" if no user account is linked.
Organization
Displays the organization name for the user's organization. Uses the OrganizationName component with batched fetching - all organization names visible on the page are fetched in a single API call (50ms debounce window).
Access to Projects
Lists all projects the driver has access to through project memberships. Uses the ProjectName component with batched fetching. Only shows projects with organization type "participation". Multiple project names are comma-separated.
Dependent API Calls
The DriverTable uses the Collection system's dependent API call feature to automatically fetch related data:
How It Works
- Initial Fetch: When you call
api.collections.driver.fetch(), the driver records are loaded - Automatic User Fetch: The collection extracts all unique
user_idvalues and makes a single batched API call to fetch user details (username, email, organization_id) - Automatic ProjectMember Fetch: The collection makes another batched call to fetch project memberships for all users, filtered to only "participation" type organizations
- Data Merging: The fetched data is merged back into the driver objects:
driver.usercontains the full user object (one-to-one relationship)driver.projectMemberscontains an array of project membership objects (one-to-many relationship)
Batched Name Lookups
The Organization and Project name columns use a separate batching mechanism:
- When the table renders, each
OrganizationNameandProjectNamecomponent requests its data viagetAsync(id) - All requests within a 50ms window are batched into a single API call using the
id__inparameter - Results are cached - if you scroll back to previously viewed rows, names are returned from cache instantly
- Console logs show:
[Collection._processBatch] X from cache: [...] | Y to fetch: [...]
This architecture ensures optimal performance even with hundreds of drivers, organizations, and projects.
Filtering
- First Name: Case-insensitive text search (
first_name__icontains)
Customization
Hide Columns
Hide specific columns using the hideColumns prop.
<DriverTable
collection={api?.collections.driver ?? null}
hideColumns={['user_id', 'modified_at']}
/>
Custom Columns
Import default columns and customize them to add or modify columns.
import { defaultDriverColumns } from '@/components/sgerp/tables/driver-table';
const customColumns = [
...defaultDriverColumns.slice(0, 2), // Name, Login
{
key: 'email',
label: 'Email',
render: (_, driver) => driver.user?.email || '-',
},
...defaultDriverColumns.slice(2), // Organization, Access to Projects
];
<DriverTable
collection={api?.collections.driver ?? null}
columns={customColumns}
/>
Custom Filters
Override the default filters with your own filter definitions.
const customFilters = [
{
key: 'first_name',
label: 'First Name',
type: 'text',
mode: 'server',
serverParam: 'first_name__icontains',
},
{
key: 'user_id',
label: 'User ID',
type: 'number',
mode: 'server',
serverParam: 'user_id',
}
];
<DriverTable
collection={api?.collections.driver ?? null}
filters={customFilters}
/>
Examples
Basic Usage with Dependent Data
A single fetch automatically loads driver, user, and project membership data.
function DriverList() {
const api = useSGERP();
React.useEffect(() => {
if (api) {
// Single fetch automatically loads driver, user, and projectmember data
api.collections.driver.fetch({ limit: 50 });
}
}, [api]);
return (
<DriverTable
collection={api?.collections.driver ?? null}
/>
);
}
Accessing Dependent Data Programmatically
Access the automatically fetched user and project membership data from driver models.
function DriverInfo() {
const api = useSGERP();
const drivers = api?.collections.driver.models ?? [];
return (
<div>
{drivers.map(driver => (
<div key={driver.id}>
<h3>{driver.first_name}</h3>
<p>Username: {driver.user?.username ?? 'No account'}</p>
<p>Email: {driver.user?.email ?? '-'}</p>
<p>Projects: {driver.projectMembers?.length ?? 0}</p>
</div>
))}
</div>
);
}
With Row Click Handler
Handle row clicks to display detailed driver information.
function DriverList() {
const api = useSGERP();
const [selectedDriver, setSelectedDriver] = React.useState<Driver | null>(null);
return (
<>
<DriverTable
collection={api?.collections.driver ?? null}
onRowClick={(driver) => setSelectedDriver(driver)}
/>
{selectedDriver && (
<div>
<h3>Selected Driver</h3>
<p>Name: {selectedDriver.first_name}</p>
<p>Login: {selectedDriver.user?.username ?? '-'}</p>
<p>Organization ID: {selectedDriver.user?.organization_id ?? '-'}</p>
<p>Access to {selectedDriver.projectMembers?.length ?? 0} projects</p>
</div>
)}
</>
);
}
Performance Notes
- Dependent calls execute once per fetch: When you fetch 50 drivers, the system makes 3 total API calls (drivers, users, projectmembers)
- Name lookups are batched: Rendering 50 organizations makes 1 API call, not 50
- Caching prevents redundant fetches: Scrolling through paginated data reuses cached names
- 50ms debounce window: Balances responsiveness with batching efficiency