级联下拉菜单未按预期工作

问题描述 投票:0回答:1

我们正在 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);
    });
  }
}

有任何帮助请更新以获取这些下拉列表中的列表和列表视图吗?

sharepoint-online react-typescript spfx webpart-connection
1个回答
0
投票

我认为使用 pnpjs 库来处理 SharePoint 的最简单方法(它是一个专门的库,在 SPFx 中也能正常工作),而不是使用内置客户端,这很混乱。

假设您从 GitHub 下载的未修改示例开始。一步一步:

    安装pnpjs:
> npm install @pnp/sp --save

  1. ListItemsWebPart.ts
    顶部添加:
import { spfi, SPFx } from "@pnp/sp"; import "@pnp/sp/webs"; import "@pnp/sp/lists"; import "@pnp/sp/views";

    将函数
  1. 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); }); }); }

    将函数
  1. 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。希望有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.