1

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
                  })
                ]
              }
            ]
          }
        ]
      };
    }
  }


5
  • You need to reset the options array inside the function and then get the SharePoint list items. Commented Mar 13, 2020 at 14:50
  • Try the solution given here and let me know if this works for you. Commented Mar 13, 2020 at 14:52
  • What are the requirements? Should the list be updated whenever the property pane is opened or when the web part is rendered on the page? Commented Mar 13, 2020 at 14:53
  • @RuneSperre I would like the dropdownlist in the property pane to render once the user clicks edit webpart. It should be dynamic , which means if user go to backend and add a new item in the list, it should reflect on the dropdown list. I would like to know what is the event to trigger the rendering when I click the Edit webpart button ?
    – Random I.T
    Commented Mar 13, 2020 at 14:57
  • @GaneshSanap, I attempted to do this.options.length =0 inside fetchList() or tried this.options =[] or tried while (this.options) {this.options.pop () or this.options.shift() there is a side effect is that after I select the list and click Add, The list will go blank. And at first place, when opens the propety panel, the list won't load, it would load after I click the Edit Webpart button twice.
    – Random I.T
    Commented Mar 13, 2020 at 15:03

1 Answer 1

1

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();
    }
  }
1
  • 1
    Thanks, didn't know the library to include was able to detect display mode and oninit to get list thanks!!!!
    – Random I.T
    Commented Mar 14, 2020 at 12:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.