techniq / mui-downshift

Thin layer over paypal's downshift to use Material UI visual components
https://techniq.github.io/mui-downshift/
MIT License
92 stars 24 forks source link

initialSelectedItem doesnt work #82

Open stragz opened 5 years ago

stragz commented 5 years ago

Im trying to use your searchable dropdowns to create a form, it works fine on a new form but if you load one that saved partially filled I cannot seem to load the dropdown from a pre-determined value.

What I'm trying to do: Load form with dropdown initial value set to Block.

How I'm trying to do it: By using initialSelectedItem as described in Downshift documentation.

<MuiDownshift
   items={dataOptions}
  variant={"outlined"}
  onStateChange={handleStateChange}
  getInputProps={({ openMenu }) => ({
    label: "Storage Type",
    placeholder: "Select Storage Type"
  })}
  // initialSelectedItem={0}
  // initialSelectedItem={"0"}
  initialSelectedItem={"Block"}
  margin="normal"
/>

Expected result: Form loads with with the the "Block" entry already selected in the dropdown

Result: I've tried different ways to specify the value but none seem to work, I always end up with the Label.

Code Sandbox: https://codesandbox.io/embed/vigorous-kalam-jzq4o

cvanem commented 5 years ago

@stragz How about this?

getInputProps={({ openMenu }) => ({
   value: "Block",
   label: "Storage Type",
   placeholder: "Select Storage Type"
})}
stragz commented 5 years ago

@cvanem Thanks for the tip, that helped get me to a good workaround. Its not quite the full solution to the problem, but its gonna do for now.

I'm now passing the desired value as a prop from the main App to the dropdown component and use that as the value in getInputProps.

const [selectedValue, setSelectedValue] = useState(props.value);

[...]

const handleStateChange = (changes: any) => {
  props.onChange(this, {
    name: props.name,
    value: changes.inputValue
  });
  setSelectedValue(changes.inputValue);
};

return (
  <FormControl fullWidth={true}>
    <Typography variant="subtitle1" color="textSecondary">
      <MuiDownshift
        items={dataOptions}
        variant={"outlined"}
        onStateChange={handleStateChange}
        getInputProps={({ openMenu }) => ({
          label: "Storage Type",
          placeholder: "Select Storage Type",
          value: selectedValue
        })}
        margin="normal"
      />
    </Typography>
  </FormControl>
);

This is the new version of the code with the workaround: https://codesandbox.io/embed/kind-dust-zlh5r

Its not ideal as it forces a value in the Input as opposed to forcing an item selection from the dropdown itself. If you open the dropdown and close it without selecting anything, both the input value and the dropdown placeholder will be overlapped.

The real solution would still be to have an initial value from the dropdown.

cvanem commented 5 years ago

@stragz That is similar to how I have been using it. I also bind the onChange event to handleStateChange and any external onChange needed. I think part of the problem is the package is still using old code. See the previous issue here for more info: https://github.com/techniq/mui-downshift/issues/79. We should probably update to 3.x.

cvanem commented 5 years ago

@stragz Here is some code I extracted/adpated from one of my redux applications. It is a little messy but might give you some direction. https://codesandbox.io/s/hardcore-curie-pxcll?fontsize=14

stragz commented 5 years ago

@cvanem Thanks alot for that, didnt initially realize that mine although allowing me to set an initial value, it broke the ability to make a search for a result.

Your help is greatly appreciated.

stragz commented 5 years ago

@cvanem quick question: in your code example, where does this come from?

import { SelectItem } from "../../general/input/SingleSelect/SingleSelect";

which package is it imported from?

cvanem commented 5 years ago

@stragz Ooops. That is just a typescript interface

export interface SelectItem {
  value: any;
  label: string;
  type?: any;
  item?: any;
}

Also take some of the comments with a grain of salt as I had to modify some of the redux compatible code to work for the code example. I.E the onChange passing the item instead of the selected value changed.

stragz commented 5 years ago

@cvanem I have another question for you, if you have a few minutes. Ive done some modification to your code in order to do a few things.

First of all I use a useQuery to get my inital data from my saved Form, then I pass my initial value to my dropdown, which was also modified to use a GraphQL query as its content list.

My issue is that when my dropdown initially loads, it doesnt yet have it's props.value initiated so it loads the dropdown as if it didnt have one. It value then gets passed as props and it is displayed as the input value but for some reason because of the timing it the label remains inside the input instead of moving in the outline. So i have 2 strings of text overlapping.

I've tried a bunch of things to try and get it to behave properly but to no avail so far. I wonder if you'd have any ideas as to how to fix my problem.

Thanks again for you help.

cvanem commented 5 years ago

@stragz If you can make a code sandbox reproduction I could take a look. The label state should be handled by the underlying MUI component, so you may need to take a look at that to see why it isn't updating. Are you sure you are updating the underlying input value? Maybe try executing blur or focus on the input ref when the value changes.

stragz commented 5 years ago

Sorry about the long delay, I've had to deal with a defective laptop and setting up my environment all over again. In the meantime one of my colleagues has managed to get something working. I'll try to setup a codesandbox in the next few days to share with everyone.

kirill-konshin commented 4 years ago

initialInputValue does not work either. This is a major issue which makes component unusable. Any expectation to fix?

kirill-konshin commented 4 years ago

@stragz in your example https://codesandbox.io/embed/kind-dust-zlh5r some errors appear in console.

image

Also if you focus the dropdown and then click out of it (without selecting anything new) it will result in this:

image

Looks like there's some state disconnect...

stragz commented 4 years ago

Warning: this is most likely overkill for most use case out there but this is what we've come up with at work (by "we" I mostly mean my colleague, the BearManGod (see code comment)).

It's a generic search dropdown using MUI-downshift which can accept a GraphQL query along with the name of the data table and the query variables to create a searchable dropdown using that queries output to feed the dropdown list.

But it can also be used with a simple array of strings as displays in the following CodeSandbox, you only need to pass the array through a function format it to what the component is expecting.

So obvisouly if you dont use GraphQL, theres alot of unnecessary code in there for you but you can always just strip it back to have it take basic arrays only. But it's a fully functionnal searchable dropdown to which you can set initial value.

https://codesandbox.io/s/vigorous-robinson-d4c5j

Hope this helps.

kirill-konshin commented 4 years ago

Thank you for the example, it will take time to dig through it :) in the mean time why not downshift's prop initialInputValue?

Any chance to boil down the example to something more reasonable for a project that just needs default value? It's hard to dig through all nuances...

Also, are there any plans to add some solution to library to address the initial value problem?