Grid
# Grid
Grid is a dataset PCF wrapper over Virtual Dataset. It allows you to use the same features that are available in the Virtual Dataset while enabling direct binding to a Subgrid or Homepage grid. This page only covers the differences between the Grid and Virtual Dataset controls. For more information about all the features available in Grid, please refer to the Virtual Dataset documentation.
Grid control on Homepage Grid with Client API support.
# Usage
Since Grid can be directly bound to a Subgrid or Homepage grid, it does not require any additional configuration. You can simply add the Grid control to your form and bind it to the desired dataset. Of course, you can still use other parameters to customize the control's behavior the same way as you would with the Virtual Dataset control. Grid behaves the same as Virtual Dataset with FetchXmlDataProvider
, so the behavior (for example in regards to the Columns
binding) is identical.
The control can be bound to a Form via the Legacy Form Designer (Modern App Designer is not supported yet). For HomePage grid, please refer to this guide (opens new window)(relevant part starts from step 5).
# Client Extensibility
Grid control supports the same Client API as the Virtual Dataset control. However, the dataset instance is acquired a bit differently depending on whether the control is used on a Subgrid or Homepage grid.
# Subgrid
When the Grid control is used on a Subgrid, the dataset instance can be acquired similarly to the Virtual Dataset control:
function onFormLoad(executionContext) {
const formContext = executionContext.getFormContext();
const control = formContext.getControl('Subgrid');
control.addOnOutputChange((executionContext) => {
const control = executionContext.getFormContext().getControl('Subgrid');
const dataset = control.getOutputs()['Subgrid.DatasetControl'].value;
dataset.addEventListener('onRecordLoaded', (record) => {
//register record expressions
})
})
}
2
3
4
5
6
7
8
9
10
11
# Homepage Grid
Getting the dataset instance in Homepage grid works a bit diffrently. Due to limited support for client scripts on Homepage grids, the dataset instance needs to be retrieved through a hidden ribbon button:
Create a Homepage grid button with an Enable Rule that always returns false. Take a note of the button's ID.
Assign a command to the button that will execute your custom JavaScript method. This method will be used to retrieve the dataset instance. Make sure to also pass
PrimaryControl
as the first parameter.Use the ribbon button ID as value for the
Client API Ribbon Button Id
parameter.If you've done everything correctly, you can retrieve the dataset instance in your custom JavaScript method like this:
function onMainGridLoad(primaryControl) {
const dataset = window.Xrm[`talxis_grid_${primaryControl.getGrid().pageId}`];
dataset.addEventListener('onRecordLoaded', (record) => {
//register record expressions
})
}
2
3
4
5
6
# Inline Ribbon
Since the control is bound to a dataset, it can interact with Power Apps ribbon buttons. You are able to whitelist specific ribbon buttons to make them render for each row. This allows for scenarios with quicker UX, since the user can click the button directly without having to select the row first.
Inline Ribbon
In order to enable this feature, you need to follow these steps:
Make sure that a column named
_talxis_gridRibbonButtons
exists on the dataset. It can either be added vialayoutXml
,Columns
binding or interceptor on columns.Input the button ID's you wisth to be visible in the Grid into the
Inline Ribbon Button Ids
parameter. The ID's should be separated by a comma. Whitelisting a button does not guarantee that Grid will render it. The button must also have an Enable Rule that evaluates to true in order to be rendered.
# Ribbon Cell Customizer
You can customize the inline ribbon cell the same way you would do with a regular cell through a PCF customizer. Once you have the customizer setup, you will receive the ribbon buttons in the RecordCommands
parameter. You can then either create a fully custom UI or leverage the GridCellRenderer
to adjust the default UI.
# Customizing the default UI
public updateView(context: ComponentFramework.Context<IInputs>): void {
ReactDOM.render(React.createElement(GridCellRenderer, {
context: context,
parameters: context.parameters,
onOverrideComponentProps(props) {
return {...props,
onGetRecordCommandsProps: (props) => {
return {
...props,
commandBarProps: {
...props.commandBarProps,
items: props.commandBarProps.items.map((item) => {
return {
...item,
iconProps: {},
className: mergeStyles({
'.ms-Button-label': {
fontWeight: 600
}
}),
text: `${this._getEmojiFromString(item.text!)} ${item.text}`,
};
}),
}
}
}
}
},
}), this._container);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# Fully Custom UI
public updateView(context: ComponentFramework.Context < IInputs > ): void {
return ReactDOM.render(React.createElement(CustomButtons, {
context: context,
commands: context.parameters.RecordCommands.raw
}), this._container)
}
export const CustomButtons = (props: ICustomButtonsProps) => {
const { context, commands } = props;
const theme = useControlTheme(context.fluentDesignLanguage);
const styles = React.useMemo(() => getCustomButtonsStyles(context.mode.allocatedHeight), [context.mode.allocatedHeight]);
return (
<ThemeProvider className={styles.customButtonsRoot} theme={theme}>
{commands.map((command) => {
return (
<PrimaryButton
disabled={!command.canExecute}
onClick={() => command.execute()}
text={command.label}
/>
);
})}
</ThemeProvider>
);
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25