简体   繁体   English

反应:通过单击按钮取消选择所有单选按钮

[英]React: Unselect all radio buttons via button click

I have a component that renders three custom radio buttons. 我有一个呈现三个自定义单选按钮的组件。 The user can either submit the selected or clear (unselect) them, leaving with no selected radio buttons. 用户可以提交选定的或清除(取消选定)它们,而没有选定的单选按钮。

I tried some options with comparing the filterResult to the data.value , but without success. 我尝试了一些比较filterResultdata.value ,但是没有成功。 Here's a simplified code: 这是一个简化的代码:

// imports
...

type Props = {
  filterConfig: PropTypes.object,
  filterValue: Proptypes.string,
  onFilterChange: PropTypes.func
}

class Filter extends React.Component {
  this.props = Props
  this.state = {
    filterValue: this.props.filterValue,
  }

  handleChange = (e) => {
    this.setState({ filterValue: e.target.value })
  }

  handleSubmit = () => {
    this.props.onFilterChange(this.state.filterValue)
    this.refs.filterContainer.close()
  }

  handleClear = () => {
    this.setState({ filterValue: '' })
  }

  renderOptions = () => {
    const { data, name } = this.props.filterConfig
    const options = data.map(
      (o, i) => (
        <div className='custom-radio' key={i}>
          <input
            id={`${name}-${i}`}
            name={name}
            onChange={this.handleChange}
            type='radio'
            value={o.value}
          />
          <label htmlFor={`${name}-${i}`}>
            <span />
            {o.label}
          </label>
        </div>
      )
    )

    return (
      <div>
        {options}
      </div>
    )
  }

  renderPickerNavigation = () => {
    return (
      <div>
        <a
          href='javascript:void(0)'
          onClick={this.handleClear}
        >
          Clear
        </a>
        <a
          href='javascript:void(0)'
          onClick={this.handleSubmit}
        >
          Done
        </a>
      </div>
    )
  }

  render = () => {
    return (
      <FilterWrapper
        ref='filterWrapper'
      >
        {this.renderOptions()}
        {this.renderPickerNavigation()}
      </FilterWrapper>
    )
  }
}

The data I'm passing in is: 我传递的数据是:

const filters = [
  {
    data: [{
      label: 'Label 1',
      value: 1
    }, {
      label: 'Label 2',
      value: 2
    }, {
      label: 'Label 3',
      value: 3
    }],
    name: 'userFilter'
  }
]

EDIT: The click event on the native radio input works fine, so no need to change that to be on the custom radio (the span element) or the label. 编辑:本机单选输入上的click事件工作正常,因此无需将其更改为自定义单选( span元素)或标签。

You should begin with having a state variable that stores which radio is currently selected. 您应该首先使用一个状态变量来存储当前选中的无线电。 The initial value for this should be null (or some other falsy value) if you want none to be pre-selected. 如果您不希望其被预先选择,则其初始值应为null (或其他虚假值)。

The reset button should trigger a function which resets this state variable back to the initial value. 重置按钮应触发将该状态变量重置回初始值的功能。


Take a look at this simple demo, using custom css radio buttons as you requested: 使用您要求的自定义CSS单选按钮 ,看看这个简单的演示:

 class MyApp extends React.Component { constructor() { super(); this.state = { selectedRadio: null, products: [{id: 1, name: "foo"}, {id: 2, name: "bar"}, {id: 3, name: "baz"}] } } select = (id) => { this.setState({selectedRadio: id}); } reset = () => { this.setState({selectedRadio: null}); } render() { return ( <div> {this.state.products.map( (item) => { return ( <div key={item.id}> <input type="radio" name="myRadio" checked={this.state.selectedRadio === item.id} /> <label onClick={this.select.bind(this, item.id)}>{item.name}<span /></label> </div> ); } )} <button onClick={this.reset}>Reset</button> </div> ); } } ReactDOM.render(<MyApp />, document.getElementById("app")); 
 div { margin: 10px 0; } input[type="radio"] { display: none; } input[type="radio"]+label span { display: inline-block; width: 14px; height: 14px; margin-left: 4px; vertical-align: middle; cursor: pointer; border-radius: 34%; } input[type="radio"]+label span { background-color: #333; } input[type="radio"]:checked+label span { background-color: orange; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="app"></div> 

Note: Since you are hiding the input element with css, you cannot have any listeners on it (eg onChange or onClick ). 注意: 由于要使用CSS隐藏输入元素,因此不能在其上放置任何侦听器(例如onChangeonClick )。 Instead, you should have onClick on the span that replaces it (see code below). 相反,您应该在替换它的span上具有onClick (请参见下面的代码)。


For a solution of how to reset all "traditional", non-css-only radio buttons , see the snippet below: 有关如何重置所有“传统”非CSS的单选按钮的解决方案,请参见下面的代码段:

 class MyApp extends React.Component { constructor() { super(); this.state = { selectedRadio: null, products: [{id: 1, name: "foo"}, {id: 2, name: "bar"}, {id: 3, name: "baz"}] } } select = (id) => { this.setState({selectedRadio: id}); } reset = () => { this.setState({selectedRadio: null}); } render() { return ( <div> {this.state.products.map( (item) => { return ( <div key={item.id}> <label>{item.name}</label> <input type="radio" name="myRadio" onChange={this.select.bind(this, item.id)} checked={this.state.selectedRadio === item.id} /> </div> ); } )} <button onClick={this.reset}>Reset</button> </div> ); } } ReactDOM.render(<MyApp />, document.getElementById("app")); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="app"></div> 

This example can help you https://codepen.io/evoyan/pen/vxGBOw 这个例子可以帮助您https://codepen.io/evoyan/pen/vxGBOw

Code: 码:

class Radio extends React.Component {
  constructor(props) {
    super(props);
    this.state = {selected: false};
  }

  toggle() {
    const {onChange} = this.context.radioGroup;
    const selected = !this.state.selected;
    this.setState({selected});
    onChange(selected, this);
  }

  setSelected(selected) {
    this.setState({selected});
  }

  render() {
    let classname = this.state.selected ? 'active' : ''
    return (
      <button type="button" className={classname} onClick={this.toggle.bind(this)}>
        {this.state.selected ? 'yes' : 'no'}
      </button>
    );
  }
}

Radio.contextTypes = {
  radioGroup: React.PropTypes.object
};

class RadioGroup extends React.Component {
  constructor(props) {
    super(props);
    this.options = [];
  }

  getChildContext() {
    const {name} = this.props;
    return {radioGroup: {
      name,
      onChange: this.onChange.bind(this)
    }};
  }

  onChange(selected, child) {
    this.options.forEach(option => {
      if (option !== child) {
        option.setSelected(!selected);
      }
    });
  }

  render() {
    let children = React.Children.map(this.props.children, child => {
      return React.cloneElement(child, {
        ref: (component => {this.options.push(component);}) 
      });
    });
    return <div className="radio-group">{children}</div>;
  }
}

RadioGroup.childContextTypes = {
  radioGroup: React.PropTypes.object
};

class Application extends React.Component {
  render() {
    return (
      <RadioGroup name="test">
        <Radio value="1" />
        <Radio value="2" />
        <Radio value="3" />
      </RadioGroup>
    );
  }
}

/*
 * Render the above component into the div#app
 */
ReactDOM.render(<Application />, document.getElementById('app'));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM