italoiz / unform-community-packages

MIT License
61 stars 10 forks source link

Integração com AutoComplete e material-ui/pickers #19

Open francisco-gonzalez opened 4 years ago

francisco-gonzalez commented 4 years ago

Alguém ja teve a necessidade e fez a integração com material-ui/pickers ou algum outro componente estilo AutoComplete, NumberFormat (react-number-format) ou MaskedInput (react-text-mask) ?

italoiz commented 4 years ago

Yes,@francisco-gonzalez, I needed that feature, but I haven't time to create this now. You can send PR to create this feature?

allandiego commented 4 years ago

I was working on Autocomplete, so far its partial functional for single and multiple values because im missing some props that im not sure how to proceed:

1 - unform ref https://material-ui.com/components/autocomplete/#custom-input autocomplete expect ref={params.InputProps.ref} but works with unform default ref={inputRef} not sure if impact anywhere

2 - setValue function in useField unform hook

3 - defaultValue prop from Autocomplete

4 - value prop from Autocomplete

5 - inputValue prop from Autocomplete

all these gonna be needed for initialData form prop and programaticaly fields sets

for options prop i have set a default type object like react-select lib:

 [
    { label: '', value: '' },
    { label: '', value: '' },
    { label: '', value: '' },
    { label: '', value: '' },
]

types.ts

import { AutocompleteProps as BaseAutocompleteProps } from '@material-ui/lab';

export interface AutocompleteOption {
  label: string;
  value: string | number;
}

export interface AutocompleteProps
  extends Omit<
    BaseAutocompleteProps<
      any,
      boolean | undefined,
      boolean | undefined,
      boolean | undefined
    >,
    'renderInput'
  > {
  name: string;
  label: string;
  options: AutocompleteOption[];
}

Autocomplete/index.tsx

import React, {
  useEffect,
  useRef,
  useState,
  useMemo,
  useCallback,
} from 'react';
import {
  CircularProgress,
  FormHelperText,
  TextField as TextInput,
} from '@material-ui/core';
import { Autocomplete as MaterialAutocomplete } from '@material-ui/lab';
import { useField } from '@unform/core';

import { AutocompleteProps, AutocompleteOption } from './types';

const Autocomplete: React.FC<AutocompleteProps> = ({
  id,
  name,
  label,
  options,
  loading,
  className,
  defaultValue,
  onChange,
  value: valueProp,
  multiple,
  style,
  children,
  ...restProps
}) => {
  const {
    fieldName,
    registerField,
    defaultValue: defaultFieldValue,
    error,
  } = useField(name);

  const inputRef = useRef(null);
  const defaultInputValue = useMemo(() => {
    if (multiple) {
      return defaultFieldValue || defaultValue || [];
    }
    return defaultFieldValue || defaultValue || '';
  }, [defaultFieldValue, defaultValue, multiple]);
  const [inputValue, setInputValue] = useState(defaultInputValue);

  const _handleChange = useCallback(
    (event, selectedOptions: AutocompleteOption | null) => {
      let value: number | number[] | string | string[];

      if (multiple && Array.isArray(selectedOptions)) {
        value = selectedOptions.map(item => String(item.value));
      } else {
        value = selectedOptions ? selectedOptions.value : '';
      }

      setInputValue(() => value);
    },
    [setInputValue, multiple],
  );

  useEffect(() => {
    if (fieldName) {
      registerField({
        name: fieldName,
        ref: inputRef.current,
        getValue() {
          return valueProp || inputValue;
        },
      });
    }
  }, [fieldName, registerField, _handleChange, valueProp, inputValue]);

  return (
    <>
      {/* <FormControl style={{ ...style }} className={className} error={!!error}> */}
      <MaterialAutocomplete
        {...restProps}
        id={id}
        options={options}
        // defaultValue={defaultInputValue || inputValue}
        loading={loading}
        multiple={multiple}

        // value/onChange real value selected by user
        // value={!valueProp ? inputValue : valueProp}
        onChange={_handleChange}

        // inputValue/onInputChange value displayed in the textbox
        // inputValue={String(inputValue)}
        // onInputChange={(event, newInputValue) => {
        //   console.log('onChange=>', newInputValue);
        //   // setInputValue(newInputValue);
        // }}

        getOptionLabel={item => item?.label}
        getOptionSelected={(option, value) => option.value === value.value}
        renderInput={params => {
          return (
            <TextInput
              {...params}
              name={name}
              label={label}
              variant="outlined"
              fullWidth
              ref={params.InputProps.ref}
              // ref={inputRef}
              InputProps={{
                ...params.InputProps,
                endAdornment: (
                  <>
                    {loading ? (
                      <CircularProgress color="inherit" size={20} />
                    ) : null}
                    {params.InputProps.endAdornment}
                  </>
                ),
              }}
            />
          );
        }}
      />

      {!!error && <FormHelperText>{error}</FormHelperText>}
      {/* </FormControl> */}
    </>
  );
};

export default React.memo(Autocomplete);
italoiz commented 4 years ago

@allandiego Can you create a fork and send a pull request? It will be better to test this feature and merge on the branch master.

guitexa commented 4 years ago

Hi guys, I'm using Autocomplete of Material-UI in my project and this feature will help me a lot, is there a release date?