Forum Discussion
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:
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;
}
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)?
- smithmeBrass 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; }); }
- smithmeBrass ContributorI 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.
- smithmeBrass ContributorI 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.
- smithmeBrass 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 }) ] } ] } ] }; }