0

I am using the TagPicker to get data dynamically and present a set of the results that matches with the term. The issue is that looking into the docs there is not clear indication how to determine that the component data is loading or searching. The interface that had those was dropped (ISuggestionsProps) and the loadingText prop does not seem to work for me or I am probably using it wrong.

here is how I was able to load data from a list into the tagpicker:

const filterSuggestedTags = async (filterText: string, tagList: ITag[]) => {
    //* possibly here to call an api if needed?
    if (filterText) {
      const url = 'url'
      const resp = await fetch(url,{method:'GET',headers:{Accept:'application/json; odata=verbose'}})
      return (await resp.json()).d.results.map(item => ({ key: item, name: item.Title }));
    } else return []
  };

codepen: https://codepen.io/deleite/pen/MWjBMjY?editors=1111

This obviously has a lot of problems, first and the worst every keystroke is a promise fired. So, question is how to call an api using the search term and result the suggestions?

Thank you all.

Ricardo Silva
  • 1,221
  • 9
  • 19

2 Answers2

0

Ok, you can mitigate this problem with the prop 'resolveDelay' but still I did not find any standard way to handle items from an api this is the closest I came up.

Any samples or ideas would be appreciated.

Ricardo Silva
  • 1,221
  • 9
  • 19
0

I am ussing Office ui Fabric react v5 ("office-ui-fabric-react": "^5.135.5"). I am using TagPicker to laod external API data (long resolve time, large data set). Loading suggestions is delayed for 700ms (after key pressed). Loading suggestions is fired after 3 chars are typed. During loading there is loading circle visible. I am loading suggestion in pages for 20 suggestions, if there is more items to be loaded on the bottom there is Loading more anchor which loads another page and add new suggestions to already loaded. I had to extend IBasePickerSuggestionsProps interface for moreSuggestionsAvailable?: boolean; in BasePicker.types.d.ts based on this issue: https://github.com/microsoft/fluentui/issues/6582

Doc: https://developer.microsoft.com/en-us/fluentui#/components/pickers

Codepen: https://codepen.io/matej4386/pen/ZEpqwQv

Here is my code:

const {disabled} = this.props;
const {
selectedItems,
    errorMessage
} = this.state;   
<TagPicker 
onResolveSuggestions={this.onFilterChanged}
getTextFromItem={this.getTextFromItem}
resolveDelay={700}
pickerSuggestionsProps={{
    suggestionsHeaderText: strings.suggestionsHeaderText,
    noResultsFoundText: strings.noresultsFoundText,
    searchForMoreText: strings.moreSuggestions,
    moreSuggestionsAvailable: this.state.loadmore
}}
onGetMoreResults={this.onGetMoreResults}
onRenderSuggestionsItem={this.onRenderSuggestionsItem}
selectedItems={selectedItems}
onChange={this.onItemChanged}
itemLimit={1}
disabled={disabled}
inputProps={{
    placeholder: strings.TextFormFieldPlaceholder
}} 
/>
private onFilterChanged = async (filterText: string, tagList:IPickerItem[]) => {
if (filterText.length >= 3) {
  let resolvedSugestions: IPickerItem[] = await this.loadListItems(filterText);

  const {
    selectedItems
  } = this.state;

  // Filter out the already retrieved items, so that they cannot be selected again
  if (selectedItems && selectedItems.length > 0) {
    let filteredSuggestions = [];
    for (const suggestion of resolvedSugestions) {
      const exists = selectedItems.filter(sItem => sItem.key === suggestion.key);
      if (!exists || exists.length === 0) {
        filteredSuggestions.push(suggestion);
      }
    }
    resolvedSugestions = filteredSuggestions;
  }
  if (resolvedSugestions) {
    this.setState({
      errorMessage: "",
      showError: false,
      suggestions: resolvedSugestions,
      loadmore: true,
      loadMorePageNumber: 1
    });

    return resolvedSugestions;
  } else {
    return [];
  }
} else {
  return null
}
}
private onGetMoreResults = async (filterText: string, selectedItems?: any[]): Promise<IPickerItem[]> => {
let arrayItems: IPickerItem[] = [];
try {
  
    let listItems: IOrganization[] = await this.GetOrganizations(this.Identity[0].id, filterText, 1);
  ...
private loadListItems = async (filterText: string): Promise<IPickerItem[]> => {
let { webUrl, filter, substringSearch } = this.props;
let arrayItems: IPickerItem[] = [];

try {
...
Matej
  • 396
  • 1
  • 9