Question

I have a Webpart Propety Panel and I would like to fetch Sharepoint List of Title and show in the Property Panel. I know how to get it going in static. Webpart.ts static way to make a drop down list

PropertyPaneDropdown('dropdownProperty', {
                  label: 'Title',
                  options: [
                    { key: 'Red', text: 'Red' },
                    { key: 'Green', text: 'Green' },
                    { key: 'DarkBlue', text: 'Dark blue' }
                  ]
                })

Dynamic Way to get the list

 PropertyPaneDropdown("dropdownProperty", {
                  label: "Title",

                  options: this.options
                }),

The Webpart class is export default class MyWebPart extends BaseClientSideWebPart< IWebPartProps

...//code continues

I wonder is there any chance I can use States, React component e.g. componentDidMount(){ fetchList(); }

So that when user edit the webparts, the user can select from the dynamic dropdown list.

I have attempted to put the fetchList() under public render() or protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {

It has some issues

  • The dropdown lists repeats it self e.g. I have 4 items, after I click edit webpart, it creates 8 , 16, ...
  • The dropdown list will go blank after I clicked the Add Button.

Thank you for reading the lengthy problem, any insght :

Tutorial for Dynamic Dropdown list https://www.sharepointnutsandbolts.com/2016/09/sharepoint-framework-spfx-web-part-properties-dynamic-dropdown.html

Webpart .ts

import * as React from "react";
import * as ReactDom from "react-dom";
import { Version } from "@microsoft/sp-core-library";
import {
  IPropertyPaneConfiguration,
  PropertyPaneTextField,
  IPropertyPaneDropdownOption,
  PropertyPaneDropdown
} from "@microsoft/sp-property-pane";
import { BaseClientSideWebPart } from "@microsoft/sp-webpart-base";

import * as strings from "AWebPartStrings";
import A from "./components/A";
import { IAProps } from "./components/IAProps";
import { IODataList } from "@microsoft/sp-odata-types";
import {
  SPHttpClient,
  SPHttpClientConfiguration,
  SPHttpClientResponse,
  ODataVersion,
  ISPHttpClientConfiguration
} from "@microsoft/sp-http";

export interface IAWebPartProps {
  description: string;
  lists: any;
  dropdownProperty: any;
}

export default class AWebPart extends BaseClientSideWebPart<IAWebPartProps> {
  private dropdownOptions: IPropertyPaneDropdownOption[];
  private listsFetched: boolean;

  private fetchLists(url: string): Promise<any> {
    return this.context.spHttpClient
      .get(url, SPHttpClient.configurations.v1)
      .then((response: SPHttpClientResponse) => {
        if (response.ok) {
          return response.json();
        } else {
          console.log(
            "WARNING - failed to hit URL " +
              url +
              ". Error = " +
              response.statusText
          );
          return null;
        }
      });
  }

  private fetchOptions(): Promise<IPropertyPaneDropdownOption[]> {
    var url =
      this.context.pageContext.web.absoluteUrl +
      `/_api/web/lists/getbytitle('mylink')/items?$select=Title,Id`;

    return this.fetchLists(url).then(response => {
      var options: Array<IPropertyPaneDropdownOption> = new Array<
        IPropertyPaneDropdownOption
      >();
      response.value.map((list: IODataList) => {
        console.log("Found list with title = " + list.Title);

        options.push({ key: list.Id, text: list.Title });
      });

      return options;
    });
  }

  public render(): void {
    const element: React.ReactElement<IAProps> = React.createElement(A, {
      description: this.properties.description,
      pagecontext: this.context.pageContext,
      SPHttpClient: this.context.spHttpClient,
      lists: this.properties.lists,
      dropdownProperty: this.properties.dropdownProperty
    });

    ReactDom.render(element, this.domElement);
  }

  protected onDispose(): void {
    ReactDom.unmountComponentAtNode(this.domElement);
  }

  protected get dataVersion(): Version {
    return Version.parse("1.0");
  }

  protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
    if (!this.listsFetched) {
      this.fetchOptions().then(response => {
        this.dropdownOptions = response;
        this.listsFetched = true;
        // now refresh the property pane, now that the promise has been resolved..
        this.onDispose();
        console.log(this.dropdownOptions);
      });
}
      return {
        pages: [
          {
            header: {
              description: strings.PropertyPaneDescription
            },
            groups: [
              {
                groupName: strings.BasicGroupName,
                groupFields: [
                  PropertyPaneTextField("description", {
                    label: strings.DescriptionFieldLabel
                  }),
                  PropertyPaneDropdown("dropdownProperty", {
                    label: "Title",
                    options: this.dropdownOptions
                  })
                ]
              }
            ]
          }
        ]
      };
    }
  }


Était-ce utile?

La solution

Try this approach.

Modify your imports:

import { Version, DisplayMode } from '@microsoft/sp-core-library';

Then, make a separate function to update the list array:

  private refreshList() {
    if (!this.listsFetched) {
      this.fetchOptions().then(response => {
        this.dropdownOptions = response;
        //this.listsFetched = true;
        console.log(this.dropdownOptions);
      });
    }
  }

Notice that I commented out the line this.listFetched = true;, else you would need to completely refresh the page for the list to refresh. I left the rest of the code intact for clarity...

Then, add the following:

  protected onInit():Promise<void> {
    if (this.displayMode !== DisplayMode.Edit) return Promise.resolve();
    return new Promise((resolve,reject)=> {
      this.refreshList();
      resolve();
    });
  }

This is called when the web part is first initialized and ensures that the list array is available when the property pane opens.

The last one will run whenever the display mode of the page is changed:

  protected onDisplayModeChanged() {
    if (this.displayMode === DisplayMode.Edit) {
      this.refreshList();
    }
  }
Licencié sous: CC-BY-SA avec attribution
Non affilié à sharepoint.stackexchange
scroll top