@material-ui/lab#AutocompleteGetTagProps TypeScript Examples

The following examples show how to use @material-ui/lab#AutocompleteGetTagProps. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: SearchFilter.Autocomplete.tsx    From backstage with Apache License 2.0 5 votes vote down vote up
AutocompleteFilter = (props: SearchAutocompleteFilterProps) => {
  const {
    className,
    defaultValue,
    name,
    values: givenValues,
    valuesDebounceMs,
    label,
    filterSelectedOptions,
    limitTags,
    multiple,
  } = props;
  const [inputValue, setInputValue] = useState<string>('');
  useDefaultFilterValue(name, defaultValue);
  const asyncValues =
    typeof givenValues === 'function' ? givenValues : undefined;
  const defaultValues =
    typeof givenValues === 'function' ? undefined : givenValues;
  const { value: values, loading } = useAsyncFilterValues(
    asyncValues,
    inputValue,
    defaultValues,
    valuesDebounceMs,
  );
  const { filters, setFilters } = useSearch();
  const filterValue =
    (filters[name] as string | string[] | undefined) || (multiple ? [] : null);

  // Set new filter values on input change.
  const handleChange = (
    _: ChangeEvent<{}>,
    newValue: string | string[] | null,
  ) => {
    setFilters(prevState => {
      const { [name]: filter, ...others } = prevState;

      if (newValue) {
        return { ...others, [name]: newValue };
      }
      return { ...others };
    });
  };

  // Provide the input field.
  const renderInput = (params: AutocompleteRenderInputParams) => (
    <TextField
      {...params}
      name="search"
      variant="outlined"
      label={label}
      fullWidth
    />
  );

  // Render tags as primary-colored chips.
  const renderTags = (
    tagValue: string[],
    getTagProps: AutocompleteGetTagProps,
  ) =>
    tagValue.map((option: string, index: number) => (
      <Chip label={option} color="primary" {...getTagProps({ index })} />
    ));

  return (
    <Autocomplete
      filterSelectedOptions={filterSelectedOptions}
      limitTags={limitTags}
      multiple={multiple}
      className={className}
      id={`${multiple ? 'multi-' : ''}select-filter-${name}--select`}
      options={values || []}
      loading={loading}
      value={filterValue}
      onChange={handleChange}
      onInputChange={(_, newValue) => setInputValue(newValue)}
      renderInput={renderInput}
      renderTags={renderTags}
    />
  );
}
Example #2
Source File: SelectionPicker.tsx    From clearflask with Apache License 2.0 4 votes vote down vote up
render() {
    const DropdownIcon = this.props.dropdownIcon || ArrowDropDownIcon;
    const onInputChange = (e, val: string, reason: AutocompleteInputChangeReason) => {
      if (reason === 'reset') return; // Prevent setting text value in textfield
      if (this.props.onInputChange) {
        this.props.onInputChange(val, reason);
      }
      if (this.props.inputValue === undefined) {
        this.setState({ inputValue: val });
      }
    };
    const renderTags = (value: Label[], getTagProps?: AutocompleteGetTagProps) => this.props.showTags === false ? null : value.map((option, index) => (
      <Fade key={option.value} in={true}>
        {this.props.bareTags ? (
          <div
            className={classNames(
              this.props.classes.chip,
              this.props.classes.chipBare,
            )}
            style={{
              color: option.color,
            }}
            {...(getTagProps ? getTagProps({ index }) : {})}
          >{option.label}</div>
        ) : (
          <Chip
            className={this.props.classes.chip}
            variant='outlined'
            label={option.label}
            size='small'
            style={{
              color: option.color,
            }}
            {...(getTagProps ? getTagProps({ index }) : {})}
          />
        )}
      </Fade>
    ));
    return (
      <Autocomplete<LabelInternal, boolean, boolean, boolean>
        freeSolo={!this.props.disableInput}
        autoHighlight
        multiple={!!this.props.isMulti}
        value={this.props.isMulti ? this.props.value : (this.props.value[0] || null)}
        onChange={(e, val, reason) => {
          // Convert create label to create-option
          var createLabel: LabelInternal | undefined;
          if (this.props.isMulti && val instanceof Array) {
            createLabel = (val as LabelInternal[]).find(label => label.isCreateOption);
          } else if (!this.props.isMulti && val instanceof Object && (val as LabelInternal).isCreateOption) {
            createLabel = (val as LabelInternal);
          }
          if (createLabel) {
            reason = 'create-option';
            val = createLabel.value;
          }

          if (reason === 'create-option') {
            var createdText: string = '';
            if (typeof val === 'string') {
              createdText = val;
            } else if (Array.isArray(val)) {
              const valParsed = val[val.length - 1];
              if (typeof valParsed === 'string') {
                createdText = valParsed;
              }
            }
            !!createdText && this.props.onValueCreate && this.props.onValueCreate(createdText);
            onInputChange(undefined, '', 'clear');
          } else if (reason === 'clear' || reason === 'blur') {
            this.props.onValueChange([]);
          } else if (reason === 'select-option' || reason === 'remove-option') {
            this.props.onValueChange(!val ? [] : (this.props.isMulti ? val as Label[] : [val as Label]));
            if (!this.props.disableClearOnValueChange) {
              onInputChange(undefined, '', 'clear');
            }
          }
        }}
        disableCloseOnSelect={this.props.disableCloseOnSelect}
        filterSelectedOptions={true}
        filterOptions={(options, params) => {
          // Sometimes autocomplete decides to pre-filter, so use options from props
          var filtered: LabelInternal[] = [...this.props.options];

          if (!this.props.disableFilter) {
            filtered = filterOptions(options, params);
          }

          // Suggest the creation of a new value
          if (!!this.props.onValueCreate && params.inputValue !== '') {
            const createLabel = {
              label: this.props.formatCreateLabel
                ? this.props.formatCreateLabel(params.inputValue)
                : `Add "${params.inputValue}"`,
              value: params.inputValue,
              groupBy: '__EMPTY__',
              isCreateOption: true,
            };
            if (this.props.showCreateAtTop) {
              filtered.unshift(createLabel);
            } else {
              filtered.push(createLabel);
            }
          }

          // Header
          if (!!this.props.formatHeader) {
            const header = this.props.formatHeader(params.inputValue);
            if (header) {
              filtered.unshift({
                label: header,
                value: '__HEADER__',
                groupBy: '__HEADER__',
                disabled: true,
              });
            }
          }

          // Add loading
          if (this.props.loading) {
            filtered.push({
              label: 'Loading…',
              value: '__HEADER__',
              groupBy: '__HEADER__',
              disabled: true,
            });
          }

          if (this.props.noOptionsMessage && filtered.length === 0) {
            filtered.push({
              label: this.props.noOptionsMessage,
              value: '__HEADER__',
              groupBy: '__HEADER__',
              disabled: true,
            });
          }

          return filtered;
        }}
        popupIcon={DropdownIcon === null ? null : (
          <DropdownIcon
            fontSize='small'
            color='inherit'
            className={this.props.value.length > 0
              ? this.props.classes.dropdownIconWithTags
              : this.props.classes.dropdownIconWithoutTags}
          />
        )}
        forcePopupIcon={this.props.forceDropdownIcon !== undefined ? this.props.forceDropdownIcon : (!!this.props.dropdownIcon || 'auto')}
        options={this.props.options}
        getOptionLabel={option => option.filterString || option.value}
        getOptionSelected={(option, value) => option.value === value.value}
        inputValue={this.props.inputValue !== undefined
          ? this.props.inputValue
          : (this.state.inputValue || '')}
        onInputChange={onInputChange}
        style={this.props.style}
        className={this.props.className}
        limitTags={this.props.limitTags}
        disabled={this.props.disabled}
        getOptionDisabled={option => !!option.disabled}
        groupBy={this.props.group ? (label: Label) => label.groupBy || label.value[0] : undefined}
        renderGroup={this.props.group ? (params: AutocompleteRenderGroupParams) => (
          <div className={classNames(this.props.classes.group, params.group === '__HEADER__' && this.props.classes.header)}>
            {params.group && params.group !== '__EMPTY__' && params.group !== '__HEADER__' && (
              <Typography key={params.key} variant='overline' className={this.props.classes.menuHeader}>{params.group}</Typography>
            )}
            {params.children}
          </div>
        ) : undefined}
        getLimitTagsText={this.props.limitTags === 0 ? more => null : undefined}
        handleHomeEndKeys
        openOnFocus
        onFocus={this.props.onFocus}
        onBlur={e => {
          if (this.props.clearOnBlur) {
            onInputChange(undefined, '', 'clear');
          }
        }}
        renderOption={(option: Label, { selected }) => (
          <Typography
            noWrap
            style={{
              fontWeight: selected ? 'bold' : undefined,
              color: option.color,
            }}
            component='div'
          >
            {(option.value !== '__HEADER__' && this.props.renderOption)
              ? this.props.renderOption(option, selected)
              : option.label}
          </Typography>
        )}
        renderTags={renderTags}
        open={this.props.menuIsOpen}
        disableClearable={this.props.disableClearable || this.props.value.length === 0}
        onOpen={this.props.menuOnChange ? () => this.props.menuOnChange && this.props.menuOnChange(true) : undefined}
        onClose={this.props.menuOnChange ? () => this.props.menuOnChange && this.props.menuOnChange(false) : undefined}
        classes={{
          ...this.props.autocompleteClasses,
          root: classNames(this.props.classes.autocomplete, this.props.autocompleteClasses?.root),
          focused: classNames(this.props.classes.autocompleteFocused, this.props.autocompleteClasses?.focused),
          popupIndicatorOpen: classNames(!!this.props.dropdownIcon && this.props.classes.dropdownIconDontFlip, this.props.autocompleteClasses?.popupIndicator),
          endAdornment: classNames(this.props.classes.endAdornment, this.props.autocompleteClasses?.endAdornment),
          input: classNames(this.props.classes.input, this.props.autocompleteClasses?.input),
          inputRoot: classNames(this.props.classes.inputRoot, this.props.autocompleteClasses?.inputRoot),
          popper: classNames(this.props.classes.popper, this.props.autocompleteClasses?.popper),
          listbox: classNames(this.props.classes.popperListbox, this.props.autocompleteClasses?.listbox),
          tag: classNames(this.props.classes.tag, this.props.autocompleteClasses?.tag),
          clearIndicator: classNames(!!this.props.clearIndicatorNeverHide && this.props.classes.clearIndicatorNeverHide, this.props.autocompleteClasses?.clearIndicator),
        }}
        PopperComponent={getSelectionPopper(this.props.PopperProps)}
        renderInput={(params) => {
          // Remove limitTags span element since it's just taking up space
          const paramsStartAdornment = (params.InputProps.startAdornment as Array<any>);
          if (this.props.limitTags === 0
            && paramsStartAdornment
            && paramsStartAdornment[0]['type'] === 'span') {
            paramsStartAdornment.shift();
          }
          const TextFieldCmpt = this.props.TextFieldComponent || TextField;
          return (
            <TextFieldCmpt
              label={this.props.label}
              helperText={this.props.errorMsg || this.props.helperText}
              placeholder={(!!this.props.bareTags && this.props.value.length > 0)
                ? undefined
                : this.props.placeholder}
              error={!!this.props.errorMsg}
              {...params}
              {...this.props.TextFieldProps}
              InputLabelProps={{
                ...params.InputLabelProps,
                ...this.props.TextFieldProps?.InputLabelProps,
              }}
              inputProps={{
                ...params.inputProps,
                ...this.props.TextFieldProps?.inputProps,
                style: {
                  minWidth: this.props.inputMinWidth === undefined
                    ? (this.props.disableInput ? 0 : 50)
                    : this.props.inputMinWidth,
                  ...this.props.TextFieldProps?.inputProps?.style,
                  maxHeight: this.props.disableInput ? 20 : undefined,
                },
              }}
              InputProps={{
                ...params.InputProps,
                ...this.props.TextFieldProps?.InputProps,
                readOnly: this.props.disableInput || this.props.TextFieldProps?.InputProps?.readOnly,
                startAdornment: (
                  <>
                    {this.props.TextFieldProps?.InputProps?.endAdornment || null}
                    {!!this.props.showTags
                      && !this.props.isMulti
                      && this.props.value.length > 0
                      && renderTags(this.props.value)}
                    {params.InputProps.startAdornment}
                    {!!this.props.alwaysWrapChipsInput && !!paramsStartAdornment?.length && (
                      <div className={this.props.classes.flexWrapBreak} />
                    )}
                  </>
                ),
                endAdornment: (
                  <>
                    {this.props.TextFieldProps?.InputProps?.endAdornment || null}
                    {params.InputProps.endAdornment}
                  </>
                ),
              }}
            />
          );
        }}
      />
    );
  }