我们正在 SPFX 中开发级联 Web 部件下拉列表,我们找到了一篇 MS 文章,这与我们正在寻找和期待的示例相同......
但在我们的例子中,我们想要使用 SP,SP 列表必须加载到第一个下拉列表中,然后相应的列表视图必须加载到第二个下拉列表中。
从 MS 文章中,我们找到两个示例函数,用于将列表加载到第一个下拉列表中,并将项目加载到第二个下拉列表中。 相反,我们需要 SP 列表,并且需要加载列表视图。
@Hugo Bernier 帮助了示例示例,该示例工作完美,但是当我们更新/替换为两个 SP 函数(加载列表和列表视图到所选列表)时
解决方案未按预期工作,它加载列表,视图正在加载到第二个下拉列表中,但当我们选择视图时,第二个下拉列表未按预期工作
这是功能
private async _getSiteLists(): Promise<string[]>{
const endpoint :string = `${this.context.pageContext.web.absoluteUrl}/_api/web/lists?$select=Title&$filter=(Hidden eq false)&$orderby=Title`;
const rawResponce: SPHttpClientResponse=await this.context.spHttpClient.get(endpoint, SPHttpClient.configurations.v1);
return(await rawResponce.json()).value.map(
(list:{Title:string})=>{
return list.Title;
}
);
}
private async _getSitelistviews(): Promise<string[]>{
//let listname:string= this.properties.SelectedList;
const endpoint :string = this.context.pageContext.web.absoluteUrl+"/_api/web/getlistbytitle('**TestList**')/views?$select=Title";
console.log("from view api",endpoint)
console.log(this.properties.SelectedList);
const rawviewResponce: SPHttpClientResponse=await this.context.spHttpClient.get(endpoint, SPHttpClient.configurations.v1);
return(await rawviewResponce.json()).value.map(
(listView:{Title:string})=>{
return listView.Title;
});}
我的理解是,我们需要将选定的值(从带有选定列表的 1 个下拉列表)传递到第二个函数,以将视图加载到该选定列表。
这是实际的代码 webpart .ts 文件
import {
IPropertyPaneConfiguration,
PropertyPaneDropdown,
IPropertyPaneDropdownOption
} from '@microsoft/sp-property-pane';
export interface IListItemsWebPartProps {
listName: string;
itemName: string;
}
export default class ListItemsWebPart extends BaseClientSideWebPart<IListItemsWebPartProps> {
private lists: IPropertyPaneDropdownOption[];
private items: IPropertyPaneDropdownOption[];
private listsDropdownDisabled: boolean = true;
private itemsDropdownDisabled: boolean = true;
private loadingIndicator: boolean = true;
public render(): void {
const element: React.ReactElement<IListItemsProps> = React.createElement(
ListItems,
{
listName: this.properties.listName,
itemName: this.properties.itemName,
}
);
ReactDom.render(element, this.domElement);
}
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
showLoadingIndicator: this.loadingIndicator,
pages: [
{
header: {
description: strings.PropertyPaneDescription
},
groups: [
{
groupFields: [
PropertyPaneDropdown('listName', {
label: strings.ListNameFieldLabel,
options: this.lists,
disabled: this.listsDropdownDisabled
}),
PropertyPaneDropdown('itemName', {
label: strings.ItemNameFieldLabel,
options: this.items,
disabled: this.itemsDropdownDisabled,
selectedKey: this.properties.itemName // don't forget to bind this property so it is refreshed when the parent property changes
})]}]}]};}
protected async onPropertyPaneConfigurationStart(): Promise<void> {
// disable the item selector until lists have been loaded
this.listsDropdownDisabled = !this.lists;
// disable the item selector until items have been loaded or if the list has not been selected
this.itemsDropdownDisabled = !this.properties.listName || !this.items;
// nothing to do until someone selects a list
if (this.lists) {
return;
}
// show a loading indicator in the property pane while loading lists and items
this.loadingIndicator = true;
this.context.propertyPane.refresh();
// load the lists from SharePoint
const listOptions: IPropertyPaneDropdownOption[] = await this.loadLists();
this.lists = listOptions;
this.listsDropdownDisabled = false;
// load the items from SharePoint
const itemOptions: IPropertyPaneDropdownOption[] = await this.loadItems();
this.items = itemOptions;
this.itemsDropdownDisabled = !this.properties.listName;
// remove the loading indicator
this.loadingIndicator = false;
this.context.propertyPane.refresh();
}
protected async onPropertyPaneFieldChanged(propertyPath: string, oldValue: any, newValue: any): Promise<void> {
if (propertyPath === 'listName' && newValue) {
// communicate loading items
this.loadingIndicator = true;
// push new list value
super.onPropertyPaneFieldChanged(propertyPath, oldValue, newValue);
// reset selected item
this.properties.itemName = ''; // use empty string to force property pane to reset the selected item. undefined will not trigger the reset
// disable item selector until new items are loaded
this.itemsDropdownDisabled = true;
// refresh the item selector control by repainting the property pane
this.context.propertyPane.refresh();
// get new items
const itemOptions: IPropertyPaneDropdownOption[] = await this.loadItems();
// store items
this.items = itemOptions;
// enable item selector
this.itemsDropdownDisabled = false;
// clear status indicator
this.loadingIndicator = false;
// refresh the item selector control by repainting the property pane
this.context.propertyPane.refresh();
}
else {
super.onPropertyPaneFieldChanged(propertyPath, oldValue, newValue);
}
}
//here is the two functions which we are trying to update to get SP lists.
private async loadLists(): Promise<IPropertyPaneDropdownOption[]> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return await new Promise<IPropertyPaneDropdownOption[]>((resolve: (options: IPropertyPaneDropdownOption[]) => void, _reject: (error: any) => void) => {
setTimeout((): void => {
resolve([{
key: 'sharedDocuments',
text: 'Shared Documents'
},
{
key: 'myDocuments',
text: 'My Documents'
}]);
}, 2000);
});
}
private async loadItems(): Promise<IPropertyPaneDropdownOption[]> {
if (!this.properties.listName) {
// return empty options since no list has been selected
return [];
}
// This is where you'd replace the mock data with the actual data from SharePoint
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return await new Promise<IPropertyPaneDropdownOption[]>((resolve: (options: IPropertyPaneDropdownOption[]) => void, reject: (error: any) => void) => {
// timeout to simulate async call
setTimeout(() => {
const items: { [key: string]: { key: string; text: string }[] } = {
sharedDocuments: [
{
key: 'spfx_presentation.pptx',
text: 'SPFx for the masses'
},
{
key: 'hello-world.spapp',
text: 'hello-world.spapp'
}
],
myDocuments: [
{
key: 'isaiah_cv.docx',
text: 'Isaiah CV'
},
{
key: 'isaiah_expenses.xlsx',
text: 'Isaiah Expenses'
}
]
};
resolve(items[this.properties.listName]);
}, 2000);
});
}
}
有任何帮助请更新以获取这些下拉列表中的列表和列表视图吗?
我认为使用 pnpjs 库来处理 SharePoint 的最简单方法(它是一个专门的库,在 SPFx 中也能正常工作),而不是使用内置客户端,这很混乱。
假设您从 GitHub 下载的未修改示例开始。一步一步:
> npm install @pnp/sp --save
ListItemsWebPart.ts
顶部添加:
import { spfi, SPFx } from "@pnp/sp";
import "@pnp/sp/webs";
import "@pnp/sp/lists";
import "@pnp/sp/views";
loadLists
替换为以下代码:
private async loadLists(): Promise<IPropertyPaneDropdownOption[]> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return await new Promise<IPropertyPaneDropdownOption[]>((resolve: (options: IPropertyPaneDropdownOption[]) => void, _reject: (error: any) => void) => {
const sp = spfi().using(SPFx(this.context));
sp.web.lists.select('Title')().then((lists) => {
const options: IPropertyPaneDropdownOption[] = lists.map((list) => {
return {
key: list.Title,
text: list.Title
};
});
resolve(options);
});
});
}
loadItems
替换为以下代码:
private async loadItems(): Promise<IPropertyPaneDropdownOption[]> {
if (!this.properties.listName) {
// return empty options since no list has been selected
return [];
}
// This is where you'd replace the mock data with the actual data from SharePoint
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return await new Promise<IPropertyPaneDropdownOption[]>((resolve: (options: IPropertyPaneDropdownOption[]) => void, reject: (error: any) => void) => {
// timeout to simulate async call
const sp = spfi().using(SPFx(this.context));
sp.web.lists.getByTitle(this.properties.listName).views.select('Title')().then((items) => {
const options: IPropertyPaneDropdownOption[] = items.map((item) => {
return {
key: item.Title,
text: item.Title
};
});
resolve(options);
});
});
}
下次请自己做。我知道您是初学者,这只是为了帮助您开始使用 SPFx。希望有帮助。