Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

onClear #1309

Closed
tim-phillips opened this issue Oct 16, 2016 · 20 comments
Closed

onClear #1309

tim-phillips opened this issue Oct 16, 2016 · 20 comments
Labels
issue/reviewed Issue has recently been reviewed (mid-2020)

Comments

@tim-phillips
Copy link

tim-phillips commented Oct 16, 2016

It could be nice to have an onClear prop where I could set a function to run when the select is cleared. That way I can update my state when the clear button is clicked.

I'm working around this by checking for an empty value in onChange.

@jfelipebc
Copy link

jfelipebc commented Oct 21, 2016

Hi @babenzele,

I had the same inconvenient, you can try this temporary solution:

import React from 'react';
import ReactDOM from 'react-dom';
import ReactSelect from 'react-select';
import 'react-select/dist/react-select.css';

function triggerMouseEvent (node, eventType) {
    var clickEvent = document.createEvent ('MouseEvents');
    clickEvent.initEvent (eventType, true, true);
    node.dispatchEvent (clickEvent);
}

export default class DropDownList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: ''
    }
  }

  onChange() {

  }

  onClear(){
    let clearElement = ReactDOM.findDOMNode(this).querySelector('.Select-clear-zone');
    triggerMouseEvent(clearElement, 'mousedown');
  }

  render() {

return (
  <div>
    <ReactSelect
      options={this.props.data}
      name='form-field-name'
      value={this.state.value}
      onChange={this.onChange.bind(this)}
      placeholder={this.props.placeholder}/>
    <span className="input-group-btn">
      <button className="btn btn-sm btn-default btn-clear"
              type="button"
              onClick={() => this.onClear()}
              title="Quitar">
        <span className="icon-cerrar"></span>
      </button>
    </span>
  </div>
)


  }
}

@tim-phillips
Copy link
Author

@jfelipebc Thanks! That's a good move putting the onClear on the clear button's onClick.

@robhadfield
Copy link

It would be great to have an onClear prop - I have a number of select boxes on the first page and athough the onChange event is fired, nothing is passed with it. It would be great to be able to pass the item object back up the onClear chain.

@jmrmgn
Copy link

jmrmgn commented Jul 26, 2019

is onClear implemented in current version?

@sclavijo93
Copy link

Hi! I really need the onClear prop :(

@beatrizmf
Copy link

News? This is extremely important! Especially if the implementer uses the new react api with hooks! ⚛ ⚓

@nikitaindik
Copy link
Contributor

Docs are not super "clear" on this, but looks like you can use second argument to onChange to detect clearing.

<Select onChange={(selectedOption, triggeredAction) => {
  if (triggeredAction.action === 'clear') {
    // Clear happened
  }
}} />

Hope this helps.

@arnaudjaspard
Copy link

Docs are not super "clear" on this, but looks like you can use second argument to onChange to detect clearing.

<Select onChange={(selectedOption, triggeredAction) => {
  if (triggeredAction.action === 'clear') {
    // Clear happened
  }
}} />

Hope this helps.

Thanks it helps, but only solves a part of the problem for me sinceis onFocus is triggered just after that so in my case it clears the state I'm using to set style on focus.
I managed with a setTimeout but it is not elegant, An alternative would be to get the value with onFocus but event.target.value is always empty for some reason. I'll spend more time to check again

@bladey bladey added the issue/reviewed Issue has recently been reviewed (mid-2020) label Jun 17, 2020
@badkuzu
Copy link

badkuzu commented Jul 24, 2020

Hey guys,
I've been struggling with this today, and I found that actually if you use a custom DropdownIndicator component, then that indicator component actually fires a state change when you click the "x" button and clear the input.
There is no handler for that though, so you have to look at props.hasValue which will change from true to false when you clear the input.
You can add the custom dropdown indicator but just not specify a custom one inside of it, then the dropdown button stays the same.

Check this sandbox that I made:
https://codesandbox.io/s/react-codesandboxer-example-bk2xy?file=/onClearEventMod.js

@bladey bladey added issue/reviewed Issue has recently been reviewed (mid-2020) and removed issue/reviewed Issue has recently been reviewed (mid-2020) labels Aug 24, 2020
@cseas
Copy link

cseas commented Sep 28, 2020

Any update on whether an onClear prop can be added to the library? Or can there be an alternate solution where we can override the onClick used by ClearIndicator?

@Methuselah96
Copy link
Collaborator

I've started a fork of react-select. Feel free to resubmit this issue on the fork and/or submit a PR to resolve this issue on the fork and we can get it merged and released.

@ebonow
Copy link
Collaborator

ebonow commented Dec 7, 2020

Greetings,

The onChange handler is meant to deal with the clear button. I understand it's not documented perhaps as well as it could be and documentation is certainly on the docket of things to address, but this is still a one and a half line code implementation to achieve the result being asked for.

Sandbox:

const selectRef = useRef();
const onChange = (_, { action }) => action === "clear" && setTimeout(() => selectRef.current.select.blur(), 1);

Yes, setTimeout is not ideal, but it does accomplish adding this to the end of the event queue after the state changes.

Given the age of this post, I will be closing this so we can continue to focus our efforts on bugs and issues. Please let me know if anyone has any issues with the provided sandbox/solution.

@ebonow ebonow closed this as completed Dec 7, 2020
@brendomaciel
Copy link

brendomaciel commented Nov 12, 2021

const selectRef = useRef();
const onChange = (_, { action }) => action === "clear" && setTimeout(() => selectRef.current.select.blur(), 1);

Does this still work? This "clear" action doesn't seems to exist anymore.

Edit

In case someone else need this, I've found that workaround:

import Select, { components } from 'react-select';
const clear = () => {
    setValue(null);
    setInputValue('');
};

const ClearIndicator = (props) => {
    const customProps = {
        ...props,
        innerProps: {
            ...props.innerProps,
            onMouseDown: clear,
        },
    };

    return <components.ClearIndicator {...customProps} />;
};
<Select
    components={{ ClearIndicator }}
    value={value}
    inputValue={inputValue}
/>

This is not the full code, but I think you can get the idea.

@ebonow
Copy link
Collaborator

ebonow commented Nov 12, 2021

@brendomaciel

clear is still a supported action passed by the actionMeta of the onChange callback and should still be working.

Screen Shot 2021-11-12 at 8 30 38 AM

What doesn't work in the sample code I provided above is the "blur" since the refs have changed from v4 -> v5. For v5, the code would instead look something like...

const onChange = (_, { action }) => action === "clear" && setTimeout(() => selectRef.current.blur(), 1);

Note that this is for an UNCONTROLLED input. For a controlled input (value is passed to the Select via its prop), then yes you would of course need to change the value in state onChange.

const [ value, setValue ] = useState();

const selectRef = useRef();

const onClear = setTimeout(() => selectRef.current.blur(), 1);

const onChange = (selected, { action }) => {
  if (action === "clear") {
    onClear();
  }
  setValue(selected);
};

return <Select ref={selectRef} value={value} onChange={onChange} {...otherProps} />

That said, your solution of creating a custom ClearIndicator component would also be a viable approach.

@brendomaciel
Copy link

@ebonow In my case onChange is not being triggered when I clear the input. This is the reason I had to bind onMouseDown in the custom component and thought that action did not exists anymore.

@ebonow
Copy link
Collaborator

ebonow commented Nov 12, 2021

@brendomaciel not sure what is happening in your implementation, but there doesn't appear to be any issues with the solution I suggested https://codesandbox.io/s/sad-grothendieck-ev5c8?file=/src/App.js

@brendomaciel
Copy link

@ebonow Thank you very much for your time and insights. I will investigate and, if I found, I will share the cause here.

@dkrefta
Copy link

dkrefta commented Jul 17, 2023

Seems that still not working for some weird reason haha anyway, I used the example of @ebonow to fix the select in my project, oh, and thanks for the example :)

here is how I create the ClearIndicator:

const ClearIndicator = ({
  innerProps,
  clearValue,
}: {
  innerProps: any;
  clearValue: () => void;
}) => {
  const handleClick = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
    event.stopPropagation();
    clearValue();
  };

  return (
    <div {...innerProps} onMouseDown={handleClick}>
      <Icon icon="close" size={16} color="black" />
    </div>
  );
};

@forrestwilkins
Copy link

I resolved the issue by just checking wether option is null since that's what's passed on clear.

@invinciblemuffi
Copy link

invinciblemuffi commented Jan 23, 2024

For reference I am pasting my code in case if it can be of help to others

const [updatedByName, setUpdatedByName] = useState([]);
const [allUpdatedByEmailIds, setAllUpdatedByEmailIds] = useState([]);
  
const updatedByEmails = result.allUpdatedByEmailIds.map(item=>{
  return {
   label:item._id,
   value:item._id
  }
})
setAllUpdatedByEmailIds(updatedByEmails);
const onUpdatedBySelectOptions = (selectedUpdatedByName, userAction) => {
    const {action, removedValue} = userAction
    if(action === 'select-option') {
      const selectedEmails = selectedUpdatedByName.map(item => item.value)
      setUpdatedByName(selectedEmails)
    }
    if(action === 'remove-value') {
      const removedEmails = selectedUpdatedByName.filter(item => item !== removedValue.value);
      setUpdatedByName(removedEmails);
    }
    if(action === 'clear') {
      setUpdatedByName([]);
    }
  };
<Select
  options={ allUpdatedByEmailIds }
  isMulti
  onChange={ onUpdatedBySelectOptions }
/>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
issue/reviewed Issue has recently been reviewed (mid-2020)
Projects
None yet
Development

No branches or pull requests