多选作为按钮组

时间:2018-03-06 22:42:09

标签: reactjs redux redux-form

我一直在转动我的车轮,试图找出一个具有redux形式的多个值的字段的最佳实践。

这就是我想要实现的目标。

enter image description here

那些buttoms是自定义组件。我通过可视化工作,使用自定义组件和import React, {Component} from 'react' import {Field} from 'redux-form' import * as icons from './../MultiSelectBtnGrid/icons' const btnStyles = { border: '3px solid #f6e9db', background: 'transparent', borderRadius: '45px', width: '250px' } const btnSelectedStyles = { border: '3px solid #27313c', background: 'transparent', borderRadius: '45px', width: '250px' } class MultiSelectField extends Component { constructor(props) { super(props) this.state = {selected: false} this.handleClick = this.handleClick.bind(this) } handleClick() { this.setState({selected: !this.state.selected}) this.props.input.onChange(!this.state.selected) } render() { const {content, idx, input: {name}} = this.props const {selected} = this.state return ( <div className={'row m-auto rel'}> <button type={'button'} className={`mb-1 p-3 ml-auto mr-auto`} style={selected ? btnSelectedStyles : btnStyles} onClick={this.handleClick}> {content} <span style={{position: 'absolute', right: '15px', top: '0', bottom: '0', margin: 'auto'}} className={'mb-1 d-flex justify-content-center align-items-center'}>{icons.plusIcon(selected)}</span> </button> <input type={'checkbox'} name={`${name}`} value={selected ? 'test' : null} checked={selected} /> </div> ) } } export default class MultiSelectBtnGroup extends Component { constructor(props) { super(props) this.state = {selected: props.formState.values[props.name]} } render() { const {options, name} = this.props return ( <div className={'container'}> <div className={'row'}> {options.map((option, idx) => { return <Field component={MultiSelectField} name={name} type='checkbox' content={option.content} key={idx} {...this.props} className={'col'} idx={idx}/> })} </div> </div> ) } } 来更新隐藏复选框字段的redux值。

这似乎是一个相当常见的用例,因为它本质上是一个多重问题。我知道使用react-widgets multiselect的文档roccomend但它似乎看起来那些符合我想要完成的按钮组样式。这是我到目前为止所看到的,但看到redux-form视图复选框是布尔值而不是数组,我不认为这对我有用。

<div class="details" itemscope itemtype="http://schema.org/Organization">
  <p class="details-organisation">
    <span itemprop="name">Test1</span>
  </p>

  <p class="details-block">
    <span itemscope itemtype="http://schema.org/Person">
      <span itemprop="name">
        John Doe
      </span>
    </span>
  </p>


  <p class="details-block">
    <span itemprop="telephone">
      +44(0)123456789
    </span>
  </p>


  <p class="details-block">
    <span itemprop="email">
      <a href="mailto:test@test123.com" data-event-category="Email a supplier" data-event-label="Test">test@test123.com</a>
    </span>
  </p>


</div>

1 个答案:

答案 0 :(得分:1)

MultiSelectBtnGroup应该是Field的组件,使值成为表单状态中的数组。

以下是一个例子:

const MultiSelectBtnGroup = { input, options } => {
    const values = input.value || [];

    const handleClick = (value, select) => {
        var index = values.indexOf(value);

        if (select) {
            if (index === -1) {
                input.onChange([...values, value]);
            }
        } else {
            if (index !== -1) {
                input.onChange(values.filter(v => v !== value));
            }
        }
    };

    return (
        <div className="row">
            {options.map(o => {
                const selected = values.indexOf(o.value) !== -1;
                return (
                    <div className="col">
                        <div className="row m-auto rel">
                            <button
                                type="button"
                                className="mb-1 p-3 ml-auto mr-auto"
                                style={selected ? btnSelectedStyles : btnStyles}
                                onClick={e => handleClick(o.value, !selected)}
                            >
                                {o.content}
                                <span
                                    style={{ position: 'absolute', right: '15px', top: 0, bottom: 0, margin: 'auto' }}
                                    className="mb-1 d-flex justify-content-center align-items-center"
                                >
                                    {icons.plusIcon(selected)}
                                </span>
                            </button>

                            <input
                                type="hidden"
                                name={name}
                                value={o.value}
                                checked={selected}
                            />
                        </div>
                    </div>
                );
            })}
        </div>
    );
};

const Example = { options, name } => (
    <div className="container">
        <Field component={MultiSelectField} name={name} />
    </div>
);

<input>不需要在那里维护表单状态,但如果您想传统提交表单,则可能会有所帮助。