InstanceGridForCustomWidget
- The
InstanceGridForCustomWidgetcomponent is wrapper component that manages data fetching, filtering, sorting, pagination, and passes the processed data and configuration toInstanceGridorInstanceGridV2for rendering a customizable, attribute-driven grid. - The component renders either:
InstanceGrid: Classic grid (server-side pagination mode)InstanceGridV2: Modern grid with virtualization, supports both server and client modes for pagination mode. - It displays the UI of
InstanceGridorInstanceGridV2, depending on widget configuration. - Supports filtering, CSV export, bulk actions, quick edit, and QR sticker printing.
- It Can be used in dashboard, view, or home layout of a custom widget.
Props
-
configuration- Type:
object - Description: Widget/grid configuration, including fields, filters, sort, page size, etc.
- Type:
-
instanceTypeName- Type:
string - Description: Name of the instance type being displayed.
- Type:
-
canCreateInstance- Type:
boolean - Description: Whether the user can create new instances.
- Type:
-
numberOfLoadingRows- Type:
number - Description: Number of skeleton rows to show while loading.
- Type:
-
isSortable- Type:
boolean - Default:
true - Description: Enables or disables sorting functionality.
- Type:
-
compact- Type:
boolean - Description: Determines if the grid should use a compact layout.
- Type:
-
gridDetails- Type:
object - Description: Additional grid configuration (e.g., versioning, view config).
- Type:
-
shrinkToFit- Type:
boolean - Description: Adjusts column widths to fit the grid.
- Type:
-
directRelatedInstance- Type:
object - Description: Data for directly related instances.
- Type:
-
sourceInstanceDetails- Type:
object - Description: Details about the source instance for the grid.
- Type:
-
relatedTypeName- Type:
string - Description: The type of related instances displayed in the grid.
- Type:
-
widgetId- Type:
string - Description: The unique ID of the widget.
- Type:
-
isFilterVisible- Type:
boolean - Default:
false - Description: Whether to show the filter UI.
- Type:
-
baseUrl- Type:
string - Description: Custom API endpoint for programmatic data fetching.
- Type:
-
programData- Type:
object - Description: Additional data to send with the custom program API call.
- Type:
-
otherUIComponents- Type:
function - Description: Function that returns additional UI components to render in the grid header.
- Type:
-
isStandardGrid- Type:
boolean - Default:
true - Description: If true, uses standard grid data fetching; otherwise, uses custom program API.
- Type:
-
widgetView- Type:
string - Default:
Grid - Description: Defines which grid version to render (Grid or GridV2).
- Type:
Notes
otherUIComponentsallows you to inject custom buttons or controls into the grid header.- For custom program API fetching, set
baseUrlandprogramDataand setisStandardGrid={false}. - In case of fetching data through custom program then for sorting and pagination we have to pass data in key-value pair format.
Response Data Structure require for Grid V2 In case of fetching data through custom program
- Custom program response must be in below format
[
{
id: 'abc-123',
name: 'Sample',
attr1: 'foo',
attr2: 42
// ...other attributes as key-value pairs
},
// ...
]
Usage Example: Instance grid V2 - Fetching data through custom program
function InstanceGridV2CustomWidget(pageContext) {
const { protrakUtils, protrakComponents } =
React.useContext(customWidgetContext);
const { InstanceGridForCustomWidget, Container, Spinner, Box, Dropdown } =
protrakComponents;
const { useTypeLayoutConfig, useProtrakApi, protrakApiClient } = protrakUtils;
let configuration = pageContext?.currentWidgetConfig;
configuration = {
...configuration,
fields: [
{
fieldType: "Attribute",
attributeType: "DateTime",
label: "CreatedDate",
isVisible: false,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "Created",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
{
fieldType: "Attribute",
attributeType: "User",
label: "Creator",
isVisible: false,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "Creator",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
{
fieldType: "Attribute",
attributeType: "Text",
label: "Description",
isVisible: false,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "Description",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
{
fieldType: "Actions",
attributeType: "Text",
label: "Actions",
isVisible: false,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "Actions",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [
{
id: "8321f283-e0aa-4896-a101-b05400511fcc",
actionType: "PromoteAction",
relationDirection: "To",
canCreateRelatedType: false,
},
{
id: "32021261-2a40-4b0a-8c7b-b05400511fcc",
actionType: "QuickEdit",
relationDirection: "To",
canCreateRelatedType: false,
},
{
id: "5da2b23d-9018-4bff-9135-b05400511fcc",
actionType: "Edit",
relationDirection: "To",
canCreateRelatedType: false,
},
{
id: "31662aa6-df93-44b4-a4e0-b05400511fcc",
actionType: "Delete",
relationDirection: "To",
canCreateRelatedType: false,
},
{
id: "b498da58-ab7b-47a5-8fb5-b05400511fcc",
actionType: "ViewDetails",
relationDirection: "To",
canCreateRelatedType: false,
},
{
id: "4ab571e7-c51c-43be-a7d1-b05400511fcc",
actionType: "OpenInNewTab",
relationDirection: "To",
canCreateRelatedType: false,
},
],
formatConditions: [],
},
{
fieldType: "Name",
attributeType: "Text",
label: "Name",
isVisible: true,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "name",
isRequired: true,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
{
fieldType: "Attribute",
attributeType: "DateTime",
label: "ModifiedDate",
isVisible: true,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "modified",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
{
fieldType: "Lifecycle",
attributeType: "Lifecycle",
label: "Lifecycle",
isVisible: false,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "Lifecycle",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
{
fieldType: "Attribute",
attributeType: "Text",
label: "GeofenceCenter",
isVisible: false,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "GeofenceCenter",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
{
fieldType: "Attribute",
attributeType: "Text",
label: "GeofenceRadius",
isVisible: false,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "GeofenceRadius",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
{
fieldType: "Attribute",
attributeType: "Picklist",
label: "Action Type",
isVisible: true,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "taskActionType",
isRequired: false,
options: [
{
name: "ManageContent",
displayName: "Manage Content",
disabled: false,
},
{
name: "KeyRotationRequest",
displayName: "Key Rotation",
disabled: false,
},
{
name: "SecurityAlert",
displayName: "Security Alerts",
disabled: false,
},
{
name: "ConfigurationArtifact",
displayName: "Configuration Artifacts",
disabled: false,
},
{
name: "UpdatePolicy",
displayName: "Update Policies",
disabled: false,
},
{
name: "BatchCertificate",
displayName: "Batch Certificates",
disabled: false,
},
],
regExErrorMessage: "",
isMultiselect: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
editor: "Default",
renderer: "Default",
},
{
fieldType: "State",
attributeType: "Text",
label: "State",
isVisible: true,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "State",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
{
fieldType: "Attribute",
attributeType: "User",
label: "Modifier",
isVisible: false,
isEditable: false,
isRelatedTypeGeolocationAttribute: false,
width: 0,
attributeName: "Modifier",
isRequired: false,
allowValueCaptureFromScan: false,
actionSettingsShowAs: "Default",
dashboardLayoutWidgetActionSettings: [],
formatConditions: [],
},
],
};
return (
<InstanceGridForCustomWidget
key={"InstanceGridForCustomWidget"}
isStandardGrid={false}
configuration={configuration}
canCreateInstance={"true"}
numberOfLoadingRows={10}
baseUrl={"programs/DynamicTypeCustomDashboard/executeCommonProgram"}
widgetView={'GridV2'}
/>
);
}
UI: InstanceGridV2

Usage Example 1 - Dashboard layout
function MemberDeviceInstanceGridForDashboardLayout(pageContext) {
const { protrakUtils, protrakComponents } =
React.useContext(customWidgetContext);
const { InstanceGridForCustomWidget, Container, Spinner, Box, Dropdown } =
protrakComponents;
const { useTypeLayoutConfig, useProtrakApi, protrakApiClient } = protrakUtils;
const [selectedOption, setSelectedOption] = React.useState({});
const [baseUrl, setBaseUrl] = React.useState(
'programs/SolrConnectorCommonProgram/executeCommonProgram'
);
const [picklistOptions, setPicklistOptions] = React.useState({
label: '',
value: '00000000-0000-0000-0000-000000000000',
});
const __getInstanceDetailsPromise__ = React.useCallback(
async ({ protrakApiClient, authContext }) => {
const apiUrl =
'instances?attributes[0]=Actions&attributes[1]=Name&attributes[3]=Modified&attributes[4]=Created&attributes[5]=TrackingInfo&attributes[6]=QRCode&getAllowedOperations=true&getAllowedActions=true&sortBy=Modified&isSortByDescending=true&instanceTypeName=DynamicGroups&getOnlyActionableInstances=false&skip=0&take=9999';
let res = await protrakApiClient(apiUrl, {}, authContext);
return res;
},
[]
);
const { state: response } = useProtrakApi({
promiseFn: __getInstanceDetailsPromise__,
protrakApiClient,
});
React.useEffect(() => {
if (response.isFulfilled && response.data && response.data.items) {
const formattedItems = response.data.items.map((item) => ({
label: item.name,
value: item.id,
}));
setPicklistOptions(formattedItems);
}
}, [response.isFulfilled, response.data]);
const dashboardConfig = useTypeLayoutConfig('MemberDevice', 'dashboard');
let configuration = {};
if (
(dashboardConfig.isLoading && !dashboardConfig.data) ||
response.isLoading
) {
return (
<Container>
<Spinner />
</Container>
);
}
if (dashboardConfig.isFulfilled && dashboardConfig.data) {
const widget = dashboardConfig.data.widgets.find(function (widget) {
return widget.name == 'MemberDeviceDashboard';
});
const objToPush = {
canCreateInstance: dashboardConfig.data.canCreateInstance,
typeName: dashboardConfig.data.typeName,
typePluralName: dashboardConfig.data.typePluralName,
typeSingularName: dashboardConfig.data.typeSingularName,
};
configuration = { ...widget, ...objToPush };
}
if (dashboardConfig.isError || response.isError) {
return (
<Container>
<h3>Server error!</h3>
</Container>
);
}
return (
<InstanceGridForCustomWidget
key={
selectedOption
? selectedOption.value
: "MemberDeviceInstanceGridForDashboardLayout"
}
isStandardGrid={false}
configuration={configuration}
canCreateInstance={'true'}
numberOfLoadingRows={10}
baseUrl={baseUrl}
programData={selectedOption && selectedOption.value}
isFilterVisible={false}
otherUIComponents={() => {
return (
<Box width={'40%'} direction={'column'} marginLeft={'1rem'}>
<Dropdown
defaultValues={selectedOption}
placeholder={'Select Dynamic Group'}
picklistOptions={picklistOptions}
onValueChange={(option) => {
if (option === null) {
setSelectedOption({
label: '',
value: '00000000-0000-0000-0000-000000000000',
});
setBaseUrl(
'programs/SolrConnectorCommonProgram/executeCommonProgram'
);
} else {
setSelectedOption(option);
setBaseUrl(
'programs/SolrConnectorCommonProgram/executeCommonProgram'
);
}
}}
isMultiselect={false}
isClearable={true}
/>
</Box>
);
}}
/>
);
}
UI: InstanceGrid

Usage Example 2 : View layout
function DynamicGroupsInstanceGridForViewLayout(pageContext) {
const { protrakUtils, protrakComponents } =
React.useContext(customWidgetContext);
const {
InstanceGridForCustomWidget,
Button,
ButtonEnums,
Container,
Spinner,
} = protrakComponents;
const { useTypeLayoutConfig } = protrakUtils;
const [baseUrl, setBaseUrl] = React.useState(
'programs/SolrConnectorCommonProgram/executeCommonProgram'
);
const [programData, setProgramData] = React.useState(
'00000000-0000-0000-0000-000000000000'
);
const dashboardConfig = useTypeLayoutConfig('MemberDevice', 'dashboard');
let configuration = {};
if (dashboardConfig.isLoading && !dashboardConfig.data) {
return (
<Container>
<Spinner />
</Container>
);
}
if (dashboardConfig.isFulfilled && dashboardConfig.data) {
const widget = dashboardConfig.data.widgets.find(function (widget) {
return widget.name == 'MemberDeviceDashboard';
});
const objToPush = {
canCreateInstance: dashboardConfig.data.canCreateInstance,
typeName: dashboardConfig.data.typeName,
typePluralName: dashboardConfig.data.typePluralName,
typeSingularName: dashboardConfig.data.typeSingularName,
};
configuration = { ...widget, ...objToPush };
}
return (
<InstanceGridForCustomWidget
isStandardGrid={false}
configuration={configuration}
canCreateInstance={pageContext.layoutConfig.canCreateInstance}
isFilterVisible={false}
baseUrl={baseUrl}
programData={programData}
otherUIComponents={() => {
return (
<Button
text={'Evaluate Rule'}
outline
appearance={ButtonEnums.Appearance.Transparent}
size={ButtonEnums.Size.Small}
onClick={() => {
setBaseUrl(
'programs/SolrConnectorCommonProgram/executeCommonProgram'
);
setProgramData(pageContext.instanceId);
}}
style={{ marginLeft: '1rem' }}
/>
);
}}
/>
);
}
UI: InstanceGrid
