From 86c2d38e85d6fb7bc97a5cf74a7dd58836b00edb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Maillot?= Date: Sun, 6 Apr 2025 21:47:07 +0200 Subject: [PATCH] Adding new prop to `ListView`: `flattenItems` --- docs/documentation/docs/controls/ListView.md | 95 ++++++++++++++++++-- src/controls/listView/IListView.ts | 11 ++- src/controls/listView/ListView.tsx | 2 +- 3 files changed, 98 insertions(+), 10 deletions(-) diff --git a/docs/documentation/docs/controls/ListView.md b/docs/documentation/docs/controls/ListView.md index 73b6e7618..c5f5dd2b5 100644 --- a/docs/documentation/docs/controls/ListView.md +++ b/docs/documentation/docs/controls/ListView.md @@ -17,13 +17,13 @@ This control renders a list view for the given set of items. - Check that you installed the `@pnp/spfx-controls-react` dependency. Check out the [getting started](../../#getting-started) page for more information about installing the dependency. - Import the following modules to your component: -```TypeScript +```typeScript import { ListView, IViewField, SelectionMode, GroupOrder, IGrouping } from "@pnp/spfx-controls-react/lib/ListView"; ``` - Use the `ListView` control in your code as follows: -```TypeScript +```typeScript { } ``` +## Disabling flatten items + +By default, the ListView control is flattening the items passed as prop, which means that nested objects such as arrays are transformed and put at level 0. This can be a problem when manipulating items with objects or sub-arrays. When setting the prop `flattenItems` to `false`, items are returned "as provided" which enables custom rendering. See the following example: + +```typescript +// ... +public render(): React.ReactElement<{}> { + const itms = [ + { + id: 1, + displayName: 'Adele Vance', + email: 'adelev@contoso.onmicrosoft.com', + managers: [{displayName: "Tony Stark"}, {displayName: "Natasha Romanoff"}] + }, + { + id: 2, + displayName: 'Alex Wilber', + email: 'alexw@contoso.onmicrosoft.com', + managers: [{displayName: "Maria Hill"}, {displayName: "Bruce Banner"}] + }, + { + id: 3, + displayName: 'Megan Bowen', + email: 'meganb@contoso.onmicrosoft.com', + managers: [{displayName: "Thor"}, {displayName: "Tony Stark"}] + }, + ]; + + const vwFields: IViewField[] = [ + { + name: "id", + displayName: "ID", + sorting: false, + minWidth: 50, + maxWidth: 50 + }, + { + name: "displayName", + displayName: "Name", + sorting: true, + minWidth: 100, + maxWidth: 100 + }, + { + name: "email", + displayName: "E-mail", + sorting: true, + minWidth: 150, + maxWidth: 150 + }, + { + name: "managers", + displayName: "Managers", + sorting: true, + render: (item?: any, index?: number, column?: any): JSX.Element => { + return ( +
+ {item.managers.map(itm => {return {itm.displayName}})} +
+ ); + }, + minWidth: 100, + maxWidth: 100 + } + ]; + + return ( + + ); +} +``` + ## Implementation The ListView control can be configured with the following properties: @@ -100,11 +180,12 @@ The ListView control can be configured with the following properties: | defaultFilter | string | no | Specify the initial filter to be applied to the list. | | dragDropFiles | boolean | no | Specify the drag and drop files area option. Default false. | | onDrop | file | no | Event handler returns files from drag and drop. | -| stickyHeader | boolean | no | Specifies if the header of the `ListView`, including search box, is sticky | +| stickyHeader | boolean | no | Specifies if the header of the `ListView`, including search box, is sticky. | | onRenderRow | (props: IDetailsRowProps) => JSX.Element \| null | no | Callback to override the default row rendering. | -| sortItems | (items: any[], columnName: string, descending: boolean) => any[] | no | Custom sorting function to handle sorting by column | -| className | string | no | Class name to apply additional styles on list view wrapper | -| listClassName | string | no | Class name to apply additional styles on list view | +| sortItems | (items: any[], columnName: string, descending: boolean) => any[] | no | Custom sorting function to handle sorting by column. | +| className | string | no | Class name to apply additional styles on list view wrapper. | +| listClassName | string | no | Class name to apply additional styles on list view. | +| flattenItems | boolean | no | Specify if items should be flatten or not. Default value is `true`. | The `IViewField` has the following implementation: diff --git a/src/controls/listView/IListView.ts b/src/controls/listView/IListView.ts index cd5b1fbd1..bbdd2322f 100644 --- a/src/controls/listView/IListView.ts +++ b/src/controls/listView/IListView.ts @@ -84,6 +84,11 @@ export interface IListViewProps { * @returns sorted collection of items */ sortItems?: (items: any[], columnName: string, descending: boolean) => any[]; // eslint-disable-line @typescript-eslint/no-explicit-any + /** + * Specify if items should be flatten or not. + * Default value is `true`. + */ + flattenItems?: boolean; } export interface IListViewState { @@ -96,11 +101,13 @@ export interface IListViewState { */ items?: any[]; // eslint-disable-line @typescript-eslint/no-explicit-any /** - * Given column defitions. + * Given column definitions. * If none are provided, default columns will be created based on the item's properties. */ columns?: IColumn[]; - + /** + * Grouping applied to the view. + */ groups?: IGroup[]; } diff --git a/src/controls/listView/ListView.tsx b/src/controls/listView/ListView.tsx index de3189935..3c4d42d9b 100644 --- a/src/controls/listView/ListView.tsx +++ b/src/controls/listView/ListView.tsx @@ -236,7 +236,7 @@ export class ListView extends React.Component { let columns: IColumn[] = null; // Check if a set of items was provided if (typeof items !== 'undefined' && items !== null) { - tempState.items = this._flattenItems(items); + tempState.items = props.flattenItems === undefined || props.flattenItems ? this._flattenItems(items) : items; } // Check if an icon needs to be shown