简体   繁体   English

Material UI Autocomplete-Popper 不会停留在渲染它的组件上

[英]Material UI Autocomplete- Popper not STUCk to the component which rendered it

Current Output of my Autocomplete is in the attached VIDEO Link wheree the atocomplete suggestions are dancing around the page as window scrolls: https://www.screencast.com/t/atbTdIaXpzu我的自动完成功能的当前 Output 位于随附的视频链接中,当 window 滚动时,Atocomplete 建议在页面上跳动: Z5E056C500A1C4B6A7110B50D807BADEcastbTZd://www.screen.

I am trying to fix the Autocomplete suggestion to the Autocomplete control and somehow Auto Suggestions dropdown sticks to the autocomplete BUT the scrolling experience within the Autocomplete is not that smooth我正在尝试将自动完成建议修复到自动完成控件,并且以某种方式自动建议下拉菜单坚持自动完成但自动完成中的滚动体验并不那么流畅

Solution used as below:使用的解决方案如下:

Using AutoComplete Property PopperComponent ={PopperMy}使用自动完成属性PopperComponent ={PopperMy}

const PopperMy = function (props) {
  return <Popper {...props} placement="bottom-start" disablePortal={true} />;
};

or this popperVariant:或者这个popperVariant:

<Popper
      {...props}
      disablePortal={true}
      placement="bottom-start"
      popperOptions={{ positionFixed: true }}
    />

Any suggestions and fixed are appreciated.任何建议和固定表示赞赏。 Thanks !谢谢 !

Adding the file contents for reference here:在此处添加文件内容以供参考:

import React, { useState, useEffect } from "react";
import {
  TextInputField,
  InputLabelField,
  BoxField,
  CustomWhiteTooltip,
} from "../../atoms";
import Autocomplete, {
  createFilterOptions,
} from "@material-ui/lab/Autocomplete";
import {
  IsArrayNotEmpty,
  IsNotEmpty,
  IsString,
  IsObject,
  IsFunction,
  ThrowException,
  IsObjectNotEmpty,
  ObjectHasKey,
  IsNotUndefined,
} from "../../../utility";
import UserMessages from "../../../constants/UserMessages";
import TextField from "@material-ui/core/TextField";
import { InfoIcon } from "../../../resources/ThemeIcons";
import { Popper } from "@material-ui/core";


const TypeaheadField = ({
  id = "",
  renderInputId = "",
  listOptions,
  mainListOptionsKey = IsString(mainListOptionsKey)
    ? mainListOptionsKey
    : "title",
  getPropertyFromSingleObject = IsString(getPropertyFromSingleObject)
    ? getPropertyFromSingleObject
    : false,
  //defaultSelected='',
  isCreatable = false,
  onChange,
  addNewLabel = "Add",
  disableClearable = false,
  className = "",
  textFieldClassName = "",
  isSelectMultiple = false,
  limitTags = -1,
  filterSelectedOptions = true,
  openOnFocus = true,
  blurOnSelect = false,
  labelAtTop = false,
  labelClassName = "",
  popupIcon,
  size = "small",
  disabled = false,
  variant = "standard",
  label = "",
  required = false,
  placeholder = "",
  fullWidth = true,
  value = "",
  ChipProps = {},
  inputLabelProps = {},
  helperText = "",
  error = false,
  onBlur = "",
  name = "",
  tooltipMessage = "",
  tooltipIcon = "",
  ...rest
}) => {
  /* Required props:  listOptions, onChange */
  const isListOptionsProvided = IsArrayNotEmpty(listOptions);
  const isOnChangeProvided = IsFunction(onChange);
  if (!isListOptionsProvided || !isOnChangeProvided) {
    //ThrowException(UserMessages.warnings.missingRequiredProps);
  }

  const [autovalue, setValue] = React.useState(value);

  useEffect(() => {
    const IsMultipleSelectAllowed = isSelectMultiple === true;
    if (IsMultipleSelectAllowed) {
      setValue(autovalue && IsArrayNotEmpty(autovalue) ? autovalue : []);
    } else if (!IsMultipleSelectAllowed) {
      setValue(autovalue && IsNotEmpty(autovalue) ? autovalue : null);
    }
  }, []);

  const handleOnChange = (event, newValue) => {
    let selectedValue = newValue;

    if (newValue && IsObject(newValue)) {
      if (newValue[mainListOptionsKey]) {
        // Create a new value from the user input
        if (newValue.type === "new") {
          if (IsString(listOptions[0])) {
            selectedValue = newValue.value;
            listOptions.push(newValue.value);
          } else {
            selectedValue = newValue.value;
            listOptions.push({
              [mainListOptionsKey]: newValue.value,
            });
          }
        }
      } else {
        const LastObject = IsArrayNotEmpty(newValue)
          ? newValue[newValue.length - 1]
          : null;
        const IsNewValueAdded =
          LastObject && LastObject.type === "new" && LastObject.value;
        if (IsNewValueAdded) {
          // Create a new value from the user input
          const CurrentValues =
            autovalue && IsArrayNotEmpty(autovalue) ? [...autovalue] : [];
          if (IsString(listOptions[0])) {
            selectedValue = [...CurrentValues, LastObject.value];
            listOptions.push(LastObject.value);
          } else {
            selectedValue = [
              ...CurrentValues,
              { [mainListOptionsKey]: LastObject.value },
            ];
            listOptions.push({ [mainListOptionsKey]: LastObject.value });
          }
        }
      }
    }

    setValue(selectedValue);
    if (
      getPropertyFromSingleObject !== false &&
      isSelectMultiple === false &&
      IsObjectNotEmpty(selectedValue) &&
      ObjectHasKey(selectedValue, getPropertyFromSingleObject)
    ) {
      onChange(selectedValue[getPropertyFromSingleObject]);
      return;
    }
    onChange(selectedValue);
  };

  const handleFilterOptions = (options, params) => {
    const filter = createFilterOptions();
    const filtered = filter(options, params);

    // Suggest the creation of a new value
    const IsSuggestNewValue = params.inputValue !== "" && isCreatable === true;
    if (IsSuggestNewValue) {
      filtered.push({
        value: params.inputValue,
        type: "new",
        [mainListOptionsKey]: `${addNewLabel} "${params.inputValue}"`,
      });
    }
    return filtered;
  };

  const handleGetOptionLabel = (option) => {
    if (typeof option === "string") {
      return option;
    }
    return option ? option[mainListOptionsKey] : null;
  };

  const handleGetOptionSelected = (option, value) => {
    if (value && IsObject(value) && IsObjectNotEmpty(value)) {
      return option[mainListOptionsKey] === value[mainListOptionsKey];
    } else if (
      option &&
      IsObject(option) &&
      IsObjectNotEmpty(option) &&
      value &&
      IsString(value) &&
      IsNotEmpty(value)
    ) {
      return option[mainListOptionsKey] === value;
    } else {
      return option === value;
    }
  };

  const handleEmptyValue = (valueParam) => {
    /**
     * TODO:: Add these in utility folder.
     */
    if (isSelectMultiple) {
      return value && IsArrayNotEmpty(value)
        ? value
        : valueParam && IsArrayNotEmpty(valueParam)
        ? valueParam
        : [];
    } else {
      if (IsObject(valueParam) || IsObject(value)) {
        return IsNotUndefined(value) &&
          value !== null &&
          IsObjectNotEmpty(value)
          ? value
          : IsNotUndefined(valueParam) &&
            valueParam !== null &&
            IsObjectNotEmpty(valueParam)
          ? valueParam
          : null;
      } else if (IsString(valueParam) || IsString(value)) {
        return IsNotEmpty(value)
          ? value
          : IsNotEmpty(valueParam)
          ? valueParam
          : null;
      }
    }
  };

  const handleOnBlur = () => {
    if (IsFunction(onBlur)) {
      onBlur();
    }
  };

  const autocompleteValue = handleEmptyValue(autovalue);

  const inputRequired =
    required === true &&
    (isSelectMultiple
      ? !IsArrayNotEmpty(autocompleteValue)
      : !IsNotEmpty(autocompleteValue));

  return (
    <Autocomplete
      className={className}
      multiple={isSelectMultiple}
      value={autocompleteValue}
      filterSelectedOptions={filterSelectedOptions}
      id={id}
      size={size}
      ChipProps={ChipProps}
      disableClearable={disableClearable}
      popupIcon={popupIcon}
      openOnFocus={openOnFocus}
      blurOnSelect={blurOnSelect}
      options={listOptions}
      limitTags={limitTags}
      onChange={handleOnChange}
      disabled={disabled}
      filterOptions={handleFilterOptions}
      getOptionLabel={handleGetOptionLabel}
      getOptionSelected={handleGetOptionSelected}
      
      name={name}
      onBlur={handleOnBlur}
      renderInput={(params) => (
        <div>
       <TextField
            {...params}
            id={renderInputId ? renderInputId : label}
            variant={variant}
            label={!labelAtTop && label}
            className={textFieldClassName}
            required={inputRequired}
            //onChange={()=>{}}
            placeholder={placeholder}
            fullWidth={fullWidth}
            InputLabelProps={inputLabelProps}
            helperText={helperText}
            error={error}           
          /> 
        </div>
      )}
    />
  );
};

export default TypeaheadField;

I'd like to see more about your code to have a better context.我想更多地了解您的代码以获得更好的上下文。 The first suggestion is to use the prop anchorEl and reference your Textfield.第一个建议是使用道具 anchorEl 并引用您的 Textfield。 You can find more about it and examples in the documentation here:您可以在此处的文档中找到有关它的更多信息和示例:

https://material-ui.com/es/components/popper/ https://material-ui.com/es/components/popper/

And also I don't know if you are using the Autocomplete component directly so let me know if you are.而且我不知道您是否直接使用自动完成组件,所以如果您是,请告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM