Я использую сгруппированный компонент пользовательского интерфейса DetailsList Fabric в пользовательской веб-части SPFx для отображения список данных.
Мне нужно динамически загружать элементы группы с сервера с помощью вызова API после расширения группы, но я не могу найти какие-либо доступные обратные вызовы расширения группы в компоненте DetailsList с доступными открытыми реквизитами группы (имя группы и т. д.) в качестве метода параметр для построения строки запроса. Это должно выглядеть так:
https://contoso.sharepoint.com/site/_api/web/Lists/getbytitle('ListTitle')/RenderListDataAsStream?@listUrl=&View=&IsGroupRender=TRUE&DrillDown=1&GroupString=%3B%23Exel%20Format%20Files%3B%23%3B%23&
По сути, я хочу добиться поведения стандартной современной веб-части библиотеки документов, существующей в Sharepoint 2019. Просто нужен обратный вызов для расширения группы для массива элементов обновления. Любые другие способы добиться этого с помощью компонента DetailsList?
Пример кода компонента (из документации):
import * as React from 'react';
import {
BaseComponent,
DefaultButton,
DetailsHeader,
DetailsList,
IColumn,
IDetailsHeaderProps,
IDetailsList,
IGroup,
IRenderFunction,
IToggleStyles,
mergeStyles,
Toggle
} from 'office-ui-fabric-react';
const margin = '0 20px 20px 0';
const controlWrapperClass = mergeStyles({
display: 'flex',
flexWrap: 'wrap'
});
const toggleStyles: Partial<IToggleStyles> = {
root: { margin: margin },
label: { marginLeft: 10 }
};
export interface IDetailsListGroupedExampleItem {
key: string;
name: string;
color: string;
}
export interface IDetailsListGroupedExampleState {
items: IDetailsListGroupedExampleItem[];
groups: IGroup[];
showItemIndexInView: boolean;
isCompactMode: boolean;
}
const _blueGroupIndex = 2;
export class DetailsListGroupedExample extends BaseComponent<{}, IDetailsListGroupedExampleState> {
private _root = React.createRef<IDetailsList>();
private _columns: IColumn[];
constructor(props: {}) {
super(props);
this.state = {
items: [
{ key: 'a', name: 'a', color: 'red' },
{ key: 'b', name: 'b', color: 'red' },
{ key: 'c', name: 'c', color: 'blue' },
{ key: 'd', name: 'd', color: 'blue' },
{ key: 'e', name: 'e', color: 'blue' }
],
// This is based on the definition of items
groups: [
{ key: 'groupred0', name: 'Color: "red"', startIndex: 0, count: 2 },
{ key: 'groupgreen2', name: 'Color: "green"', startIndex: 2, count: 0 },
{ key: 'groupblue2', name: 'Color: "blue"', startIndex: 2, count: 3 }
],
showItemIndexInView: false,
isCompactMode: false
};
this._columns = [
{ key: 'name', name: 'Name', fieldName: 'name', minWidth: 100, maxWidth: 200, isResizable: true },
{ key: 'color', name: 'Color', fieldName: 'color', minWidth: 100, maxWidth: 200 }
];
}
public componentWillUnmount() {
if (this.state.showItemIndexInView) {
const itemIndexInView = this._root.current!.getStartItemIndexInView();
alert('first item index that was in view: ' + itemIndexInView);
}
}
public render() {
const { items, groups, isCompactMode } = this.state;
return (
<div>
<div className = {controlWrapperClass}>
<DefaultButton onClick = {this._addItem} text = "Add an item" styles = {{ root: { margin: margin } }} />
<Toggle label = "Compact mode" inlineLabel checked = {isCompactMode} onChange = {this._onChangeCompactMode} styles = {toggleStyles} />
<Toggle
label = "Show index of first item in view when unmounting"
inlineLabel
checked = {this.state.showItemIndexInView}
onChange = {this._onShowItemIndexInViewChanged}
styles = {toggleStyles}
/>
</div>
<DetailsList
componentRef = {this._root}
items = {items}
groups = {groups}
columns = {this._columns}
ariaLabelForSelectAllCheckbox = "Toggle selection for all items"
ariaLabelForSelectionColumn = "Toggle selection"
onRenderDetailsHeader = {this._onRenderDetailsHeader}
groupProps = {{
showEmptyGroups: true
}}
onRenderItemColumn = {this._onRenderColumn}
compact = {isCompactMode}
/>
</div>
);
}
private _addItem = (): void => {
const items = this.state.items;
const groups = [...this.state.groups];
groups[_blueGroupIndex].count++;
this.setState(
{
items: items.concat([
{
key: 'item-' + items.length,
name: 'New item ' + items.length,
color: 'blue'
}
]),
groups
},
() => {
if (this._root.current) {
this._root.current.focusIndex(items.length, true);
}
}
);
};
private _onRenderDetailsHeader(props: IDetailsHeaderProps, _defaultRender?: IRenderFunction<IDetailsHeaderProps>) {
return <DetailsHeader {...props} ariaLabelForToggleAllGroupsButton = {'Expand collapse groups'} />;
}
private _onRenderColumn(item: IDetailsListGroupedExampleItem, index: number, column: IColumn) {
const value = item && column && column.fieldName ? item[column.fieldName as keyof IDetailsListGroupedExampleItem] || '' : '';
return <div data-is-focusable = {true}>{value}</div>;
}
private _onShowItemIndexInViewChanged = (event: React.MouseEvent<HTMLInputElement>, checked: boolean): void => {
this.setState({ showItemIndexInView: checked });
};
private _onChangeCompactMode = (ev: React.MouseEvent<HTMLElement>, checked: boolean): void => {
this.setState({ isCompactMode: checked });
};
}
Я искал это и сегодня, и после проверки исходного кода я понял это. Используйте groupProps.headerProps
, чтобы установить обратный вызов при сворачивании/расширении группы.
<DetailsList
...
groupProps = {{
headerProps: {
onToggleCollapse: this._onGroupToggleCollapse
}
}}
/>
Есть ли шанс, что вы узнали, как получить доступ к IGroupedList из DetailsList? Я просто хочу использовать метод для переключения группы, раскрывающейся/сворачивающейся, как это делает строка заголовка.
Итак, основная логика этого действия (с использованием обратного вызова onToggleCollapse):
private _onToggleCollapse(props: IGroupDividerProps): () => void {
...
if (props.group.data.isLoaded === false && props.group.isCollapsed === false && props.group.level > 0) {
...
let data: any = this._getGroupItems(props.group, isLoadAll, {}).then((resp: any) => {
resp.json().then((responseJSON: any) => {
...
updatedItems = this.state.items.map((el: any, i: number) => {
...
});
...
this.setState({
items: [...updatedItems],
groups: [...this.state.groups]
});
});
});
...
}
...
return () => {
props.onToggleCollapse!(props!.group!);
};
}
Нам нужно проверить расширение, чтобы предотвратить обновление при сворачивании группы.
Спасибо за ответ! На самом деле, я нашел способ сам некоторое время назад.