Реагировать - динамически создавать флажки выбора всех - PullRequest
0 голосов
/ 18 июня 2019

Был ряд вопросов по флажкам React. Этот ответ довольно хорош, и он помогает модулировать идею выбора всех флажков в React.

Теперь у меня проблема.У меня есть словарь, подобный следующему:

{
  regionOne: {
    subareaOne,
    subareaTwo,
    subareaThree,
    subareaFour
  },
  regionTwo: {
    subareaFive,
    subareaSix
  }
}

Здесь каждый регион сопоставляется с произвольным количеством подобластей, которые я заранее не знаю.

Я хочу создать флажки, чтобыу каждого региона и каждого подрайона есть флажок, и флажок каждого региона действует как выбор-все / отмена выбора всех для всех подрайонов, которым он сопоставлен.То есть что-то вроде этого:

enter image description here

enter image description here

Итак, когда вы нажимаете нафлажок для regionOne, флажки для subareaOne, subareaTwo, subareaThree и subareaFour также должны быть проверены, но не для regionTwo.

Я думаю, что я могу адаптироваться этот ответ , но его функция getInitialState предполагает, что вы знаете, как много дочерних флажков.

Есть идеи, как это сделать элегантным методом?Сейчас я рассматриваю возможность динамической инициализации флажков с использованием сопоставления, но я не уверен ... VanillaJS был бы намного проще>. <</p>

Ответы [ 2 ]

1 голос
/ 21 июня 2019

Я на самом деле пошел вперед и реализовал его в любом случае. Участвуют два компонента: родительский CheckboxGroup компонент и дочерний StatelessCheckbox компонент.

Вот родительский компонент:

import React from 'react';

import { StatelessCheckbox } from './StatelessCheckbox';

export class CheckboxGroup extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            checked: false,
            boxes: {},
            disabled: false
        };
    }

    componentDidMount() {
        const { boxes, boxId, disabled } = this.props;
        let boxesState = {};
        boxes.map(box => {
            boxesState[box[boxId]] = false;
        });
        this.setState({ checked: false, boxes: boxesState, disabled: disabled });
    }

    handleSelectAll(event) {
        const isChecked = event.target.checked;

        let boxesState = {};
        Object.keys(this.state.boxes).map(box => {
            boxesState[box] = isChecked;
        });
        this.setState({ checked: isChecked, boxes: boxesState });
    }

    handleSelect(event) {
        const isChecked = event.target.checked;
        const boxId = event.target.value;

        let newBoxes = {};
        Object.assign(newBoxes, this.state.boxes);
        newBoxes[boxId] = isChecked;

        // Check parent checkbox if all children boxes are checked
        const checkedBoxes = Object.keys(newBoxes).filter((box) => {
            return newBoxes[box] === true;
        });
        const parentIsChecked = (checkedBoxes.length === Object.keys(newBoxes).length);

        this.setState({ checked: parentIsChecked, boxes: newBoxes });
    }

    render() {
        const {
            passDataToParent=(() => { return false; }),
            groupClassName='',
            headClassName='',
            headName='',
            headBoxClass='',
            headLabelClass='',
            headLabelText='',
            bodyClassName='',
            bodyName='',
            bodyBoxClass='',
            bodyLabelClass='',
            boxes,
            boxId,
            boxLabel
        } = this.props;

        return (
            <div className="row">
                <div className={ groupClassName }>
                    <div className={ headClassName }>
                        <StatelessCheckbox name={ headName } className={ headBoxClass }
                                           labelClass={ headLabelClass } labelText={ headLabelText }
                                           checked={ this.state.checked } value={ headName }
                                           passedOnChange={ (e) => { this.handleSelectAll(e); } } />
                    </div>
                    <div className={`row ${ bodyClassName }`}>
                        { boxes.map(box => (
                            <div key={ box[boxId] }>
                                <StatelessCheckbox name={ bodyName } className={ bodyBoxClass }
                                                   labelClass={ bodyLabelClass } labelText={ box[boxLabel] }
                                                   checked={ this.state.boxes[box[boxId]] } value={ box[boxId] }
                                                   passedOnChange={ (e) => { this.handleSelect(e); } } />
                            </div>
                        ))}
                    </div>
                </div>
            </div>
        );
    }
}

а вот дочерний компонент:

import React from 'react';

/**
 * Implements a React checkbox as a stateless component.
 */
export class StatelessCheckbox extends React.Component {

    constructor(props) {
        super(props);
    }

    render() {
        const {
            passedOnChange=(() => { return false; }),
            className='',
            name='',
            labelClass='',
            labelText='',
            value='',
            checked=false,
        } = this.props;

        return (
            <label className={`for-checkbox ${ className }`} tabIndex="0">
                <input onChange={(e) => passedOnChange(e) }
                       checked={ checked } type="checkbox"
                       name={ name } value={ value } />
                <span className={`label ${ labelClass }`}>{ labelText }</span>
            </label>
        );
    }
}

Что следует отметить:

  • дочерний компонент в этом случае является компонентом без сохранения состояния, используемым исключительно для рендеринга
  • родительский компонент (CheckboxGroup) также поддерживает состояние для всех дочерних компонентов, поэтому все еще существует единственный источник истины согласно Философия реагирования
  • boxes в свойствах - это список дочерних флажков для каждого родителя CheckboxGroup, а boxes в родительском состоянии содержит состояние для каждого дочернего флажка
0 голосов
/ 18 июня 2019

Что-то в этом роде?

onSelect(id) {
    let allElms = Object.assign({}, retriveElmentsSomehow());
    let elm = findTheElm(id, allElms);
    updateSelected(elm, !elm.selected);
    // Then update state with new allElms
}

updateSelected(elm, selectedOrNot) {
    elm.selected = selectedOrNot;
    if (elm.children) {
        elm.children.foreach(c => onSelect(c, selectedOrNot));
    }
}

Где элементы находятся в состоянии или в хранилище с избыточностью.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...