klee-contrib / focus-components

Version 2. A set of web components based on material design to build modern interfaces easily. New version 3 is available
https://github.com/get-focus
MIT License
27 stars 34 forks source link

[RadioSelect] State in Radio #1542

Open c3dr0x opened 6 years ago

c3dr0x commented 6 years ago

Current behaviour

When using a RadioSelect the onChange given to Radio doens't take into account the value given by Radio. But Radio keeps anyway an internal state on wether it's checked or not. So if you want click on it, wanting to uncheck it, it will, but the parent won't know about it.

Expected behaviour

Radio souhldn't keep an internal state.

Versions

Focus-components: [2.2.0]

Possible fix

import React, { Component, PropTypes } from 'react';
import Translation from '../../../behaviours/translation';
import GridBehaviour from '../../../behaviours/grid';
import MaterialBehaviour from '../../../behaviours/material';
import filterProps from '../../../utils/filter-html-attributes';
import isUndefined from 'lodash/lang/isUndefined';

@Translation
@MaterialBehaviour('inputMdl')
@GridBehaviour
class Radio extends Component {

    static defaultProps = {
        value: false
    };

    static propTypes = {
        label: PropTypes.string.isRequired,
        name: PropTypes.string,
        value: PropTypes.bool,
        onChange: PropTypes.func
    };

    componentDidMount() {
        this.updateCheckedClass();
    }

    componentDidUpdate() {
        this.updateCheckedClass();
    }

    updateCheckedClass() {
        const { inputMdl } = this.refs;
        const isChecked = this.getValue();
        if (inputMdl) {
            const { classList } = inputMdl;
            if (isChecked === true) classList.add('is-checked');
            if (isChecked === false) classList.remove('is-checked');
        }
    }

    /**
    * Executed actions on change event.
    * @param  {event} event
    */
    _onChange = () => {
        if (this.props.onChange) {
            this.props.onChange();
        }
    }

    /**
    * Get the value from the input in  the DOM.
    * @returns The DOM node value.
    */
    getValue() {
        return isUndefined(this.props.value) ? false : this.props.value
    }

    /**
    * Render the Checkbox HTML.
    * @return {VirtualDOM} - The virtual DOM of the checkbox.
    */
    render() {
        const isChecked = this.getValue();
        const { label } = this.props;
        const validInputProps = filterProps(this.props);

        validInputProps.onChange = this._onChange;
        validInputProps.checked = isChecked ? 'checked' : undefined;
        const inputProps = { ...validInputProps };

        return (
            <label className='mdl-radio mdl-js-radio mdl-js-ripple-effect' data-focus='input-radio' ref='inputMdl'>
                <input className='mdl-radio__button' type='radio' ref='inputRadio' {...inputProps} />
                <span className='mdl-radio__label'>{this.i18n(label)}</span>
            </label>
        );
    }
}

Radio.displayName = 'InputRadio';

export default Radio;