Forum Discussion

smithme's avatar
smithme
Brass Contributor
Sep 25, 2019

Webpart list property using PNPJS

I am writing a simple web part. It takes a property of "List". The user will pick the list from a dropdown. I am using the tutorial found here:

https://www.sharepointnutsandbolts.com/2016/09/sharepoint-framework-spfx-web-part-properties-dynamic-dropdown.html

 

I have the following function that uses PNPJS to return an array of the lists on the site.

 

  protected fetchLists(): Array<IPropertyPaneDropdownOption> {
    let options: Array<IPropertyPaneDropdownOption> = new Array<IPropertyPaneDropdownOption>();
    sp.web.lists.select('ID', 'Title', 'DefaultViewUrl').get().then(function(data) {
      for (let i = 0; i < data.length; i++) {
        if (data[i].DefaultViewUrl.includes('/Lists/')) {
          options.push({
            key: data[i].Title,
            text: data[i].Title,
          });
        }
      })
      console.log(options);
    });
    return options;
  }

 

The above function is called in the getPropertyPaneConfiguration with the line: 
let lists: Array<IPropertyPaneDropdownOption> = this.fetchLists();

 

  protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
    let lists: Array<IPropertyPaneDropdownOption> = this.fetchLists();
    return {
      pages: [
        {
          header: {
            description: this.description
          },
          groups: [
            {
              groupName: 'Properties',
              groupFields: [
                PropertyPaneDropdown('list', {
                  label: 'List',
                  options: lists
                }),
                PropertyPaneTextField('field', {
                  label: 'Field'
                })
              ]
            }
          ]
        }
      ]
    }  
  }

 

 

The problem is the sp.web.lists... call is seen by the editor as not ways returning a value. I have tried to use the .then(function() {}) to return the array but the IDE still says not all paths return a value. How can I satisfy the IDE and still always get a return array (even if it is empty)?

  • smithme's avatar
    smithme
    Brass Contributor

    So I made the following changes. I added the catch method and put another return in there but the IDE still doesn't think that my code always returns as a value.

     

      protected fetchLists(): Array<IPropertyPaneDropdownOption> {
        let options: Array<IPropertyPaneDropdownOption> = new Array<IPropertyPaneDropdownOption>();
        sp.web.lists.select('ID', 'Title', 'DefaultViewUrl').orderBy('Title').get().then(function(data) {
          for (let i = 0; i < data.length; i++) {
            if ((data[i].DefaultViewUrl.includes('/Lists/')) && 
            (
              (data[i].Title != 'SharePointHomeCacheList') || 
              (data[i].Title != 'TaxonomyHiddenList')
            )) {
              options.push({
                key: data[i].Title,
                text: data[i].Title,
              });
            }
          }
          return options;
        }).catch(function(e) {
          return options;
        });
      }

     

  • smithme's avatar
    smithme
    Brass Contributor
    I also tried to change the return object of the function to "any", and that will compile but the list doesn't come out in the right format for the getPropertyPaneConfiguration method.
  • smithme's avatar
    smithme
    Brass Contributor
    I have concluded that my problem is asynchronous code execution. I have two functions that return a value. function A calls function B and needs to wait for the reply before it continues. This may be more complicated because function B calls another function with a callback. That I can't figure out is how to make function B a callback when I don't control when function A gets called.

  • smithme's avatar
    smithme
    Brass Contributor

    This is what I am left with for now. My this.lists object is still empty before it gets to the PropertyPaneDropdown object and I don't know what to do to fix that.

     

      protected fetchOptions(): IPropertyPaneDropdownOption[] {
        var options: Array<IPropertyPaneDropdownOption> = new Array<IPropertyPaneDropdownOption>();
        sp.web.lists.select('ID', 'Title', 'DefaultViewUrl').orderBy('Title').get().then(function(data){
          for (let i = 0; i < data.length; i++) {
            options.push({
              key: data[i].Title,
              text: data[i].Title
            })
          }
          return options;
        });
        return null;
      }
    
      protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
    
        if (!this.lists) {
          this.lists = this.fetchOptions();
          this.onDispose();
        }
    
        return {
          pages: [
            {
              header: {
                description: this.description
              },
              groups: [
                {
                  groupName: 'Properties',
                  groupFields: [
                    PropertyPaneDropdown('list', {
                      label: 'List',
                      options: this.lists
                    })
                  ]
                }
              ]
            }
          ]
        };
      }

Resources