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

Getting value onBlur #186

Closed
anthonator opened this issue May 12, 2015 · 5 comments
Closed

Getting value onBlur #186

anthonator opened this issue May 12, 2015 · 5 comments
Milestone

Comments

@anthonator
Copy link

Is it possible to get the value of select on blur? Unlike onChange onBlur returns an event. So when I do something like e.target.value I always get an empty string.

@dcousens
Copy link
Collaborator

@anthonator I'm not familiar, but with a typical onBlur event for a text box, is the e.target.value the text from the text box? We should probably mimic typical components in this respect.

@dcousens dcousens self-assigned this May 18, 2015
@anthonator
Copy link
Author

Yes, e.target.value is the value of the input.

@dcousens dcousens added todo and removed question labels May 18, 2015
@dcousens dcousens modified the milestones: 0.4.9, 0.4.10 May 18, 2015
@at0g
Copy link

at0g commented May 29, 2015

👍 for adding this.

would be nice if the first argument passed to the onChange callback was a similar event rather than just the value.

P.S This issue was killing me today in conjunction with #188, as I want to trigger validation after the initial blur event, then on subsequent change events.

If anyone else is in a similar situation, I ended up resolving it with this wrapper component.
The faux event objects are naive, but I only need e.type and e.target.value

'use strict';

var React = require('react');
var Select = require('react-select');

module.exports = React.createClass({

    displayName: 'SelectWrapper',

    getDefaultProps () {
        return {
            value: null
        }
    },

    getInitialState () {
        return {
            value: this.props.value
        }
    },

    onBlur () {
        let blurHandler = this.props.onBlur;
        if (blurHandler) {
            blurHandler({
                type: 'blur',
                target: {
                    value: this.state.value
                }
            })
        }
    },

    onChange (value) {

        let changeHandler = this.props.onChange;
        if (changeHandler) {
            changeHandler({
                type: 'change',
                target: {
                    value: value
                }
            });
        }

        this.setState({ value: value });
    },

    render () {
        let { onBlur, onChange, value, ...props } = this.props;

        return (
            <Select onBlur={ this.onBlur } onChange={ this.onChange } { ...props } { ...this.state } />
        );
    }

});

@dh376
Copy link

dh376 commented Sep 6, 2016

+1

@arungowda27
Copy link

arungowda27 commented Jun 11, 2020

👍 for adding this.

would be nice if the first argument passed to the onChange callback was a similar event rather than just the value.

P.S This issue was killing me today in conjunction with #188, as I want to trigger validation after the initial blur event, then on subsequent change events.

If anyone else is in a similar situation, I ended up resolving it with this wrapper component.
The faux event objects are naive, but I only need e.type and e.target.value

'use strict';

var React = require('react');
var Select = require('react-select');

module.exports = React.createClass({

    displayName: 'SelectWrapper',

    getDefaultProps () {
        return {
            value: null
        }
    },

    getInitialState () {
        return {
            value: this.props.value
        }
    },

    onBlur () {
        let blurHandler = this.props.onBlur;
        if (blurHandler) {
            blurHandler({
                type: 'blur',
                target: {
                    value: this.state.value
                }
            })
        }
    },

    onChange (value) {

        let changeHandler = this.props.onChange;
        if (changeHandler) {
            changeHandler({
                type: 'change',
                target: {
                    value: value
                }
            });
        }

        this.setState({ value: value });
    },

    render () {
        let { onBlur, onChange, value, ...props } = this.props;

        return (
            <Select onBlur={ this.onBlur } onChange={ this.onChange } { ...props } { ...this.state } />
        );
    }

});

You might want to slightly change this.
OnBlur can trigger very quickly after onChange. setState is async call. So if you are calling changeHandler and then setState, there's a good chance that you might have not received the value you have set in state for onBlur event.
Try this scenario

  1. Select the option
  2. OnChange triggers and ChangeHandler() is called (state value is null)
  3. The selected value is returned through your ChangeHandler() but state value is still null.
  4. Setstate is called to assign the selected option to state (no guarantee on state value to be set immediately since it is asynchronous)
  5. OnBlur is triggered immediately (if you are not using 'blurInputOnSelect' prop to keep the focus still)
  6. At this point state value might have not been set yet (state value still could be null)

But here you were expecting the state value which was set by OnChange

So you could first call setState and use the callback to trigger OnChangeHandler

onChange = (e) => {
        const { value } = e
        let changeHandler = this.props.clickHandler;
        this.setState({ value: value }, () => {
            if (changeHandler) {
                changeHandler({
                    value: value,
                    name: this.props.name
                });
            }
        });
    }
    onBlur = () => {
        const { value } = this.state;
        let blurHandler = this.props.blurHandler;
        if (blurHandler) {
            blurHandler({
                value: value,
                name: this.props.name,
            })
        }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants