Reactjs ToggleButtonGroup с типом радио не работает

Я пытаюсь реализовать группу кнопок в reactjs es6. теперь я взял этот пример https://react-bootstrap.github.io/components/button-group/ с флажком, и я пытаюсь реализовать, но, похоже, он не запускает событие onchange.

    class ToggleButtonGroupControlled extends React.Component {
          constructor(props, context) {
            super(props, context);

            //this.handleChangeEvent = this.handleChangeEvent.bind(this);

            this.state = {
              value: 1
            };
          }

          handleChangeEvent(e) {
              console.info(e);
            this.setState({ value: e });
          }

          render() {
            return (
              <ToggleButtonGroup
                type = "radio"
                    name = "exemption_status_button"
                value = {this.state.value}
                onChange = {this.handleChangeEvent.bind(this)}
              defaultChecked = {this.state.value}
              >
                <ToggleButton onChange = {this.handleChangeEvent}value = {1} className = "badge2" data-count = {this.props.statusButton.requested}>Requested</ToggleButton>
                <ToggleButton onChange = {this.handleChangeEvent}value = {3} className = "badge2" data-count = {this.props.statusButton.accepted}>Accepted</ToggleButton>
                <ToggleButton onChange = {this.handleChangeEvent}value = {6} className = "badge2" data-count = {this.props.statusButton.implemented}>Implemented</ToggleButton>
                <T

oggleButton onChange = {this.handleChangeEvent}value = {5} className = "badge2" data-count = {this.props.statusButton.cancelled}>Cancelled</ToggleButton>
            <ToggleButton onChange = {this.handleChangeEvent}value = {4} className = "badge2" data-count = {this.props.statusButton.rejected}>Rejected</ToggleButton>
          </ToggleButtonGroup>
        );
      }
    }

у меня это работает следующим образом. Мне пришлось использовать jquery для извлечения значения и использования функций возврата.

import _ from 'lodash';
import axios from 'axios';
import React, { Component } from 'react';
import { Checkbox } from 'react-bootstrap';
import { connect } from 'react-redux';
import {
    fetchSecurityExemptions,
    fetchSecurityExemptionsCount,
    fetchMarkets,
    fetchServiceDomains,
    fetchServicesList,
    fetchSecurityEngineerList,
    fetchBusinessPriorityList,
    updateSecurityExemption
} from '../../actions/security';
import { bindActionCreators } from 'redux';
import { Button, ButtonToolbar, Modal, Tooltip, OverlayTrigger, ToggleButton, ToggleButtonGroup } from 'react-bootstrap';
import FontAwesome from 'react-fontawesome';
import { BootstrapTable, TableHeaderColumn, InsertModalHeader, InsertModalFooter, SearchField } from 'react-bootstrap-table';
import 'react-bootstrap-table/dist/react-bootstrap-table-all.min.css';
import $ from 'jquery';
import ModalError from '../modalerror';
import ModalConfirm from '../modalconfirm';
import { Link } from 'react-router-dom';
import { isGenericName } from '../../scripts/validation';

class ToggleButtonGroupControlled extends Component {
      constructor(props, context) {
        super(props, context);

        this.handleChangeEvent = this.handleChangeEvent.bind(this);

        this.value = 1

      }

      handleChangeEvent(e) {
        this.value = $(e.target).children('input').val();
        this.passStatusButtonBack();
      }

      passStatusButtonBack(){
          this.props.passStatusButtonBack(this.value);
      }

      render() {
        return (
        <ButtonToolbar>
          <ToggleButtonGroup
            type = "radio"
            name = "exemption_status_button"
            value = {this.value}
            onChange = {this.handleChangeEvent}
            defaultChecked = {this.value}
          >
            <ToggleButton onClick = {this.handleChangeEvent}value = {1} className = "badge2" data-count = {this.props.statusButton.requested}>Requested</ToggleButton>
            <ToggleButton onClick = {this.handleChangeEvent}value = {3} className = "badge2" data-count = {this.props.statusButton.accepted}>Accepted</ToggleButton>
            <ToggleButton onClick = {this.handleChangeEvent}value = {6} className = "badge2" data-count = {this.props.statusButton.implemented}>Implemented</ToggleButton>
            <ToggleButton onClick = {this.handleChangeEvent}value = {5} className = "badge2" data-count = {this.props.statusButton.cancelled}>Cancelled</ToggleButton>
            <ToggleButton onClick = {this.handleChangeEvent}value = {4} className = "badge2" data-count = {this.props.statusButton.rejected}>Rejected</ToggleButton>
          </ToggleButtonGroup>
        </ButtonToolbar>
        );
      }
    }


class SecurityExemptions extends Component {
    constructor(props) {
        super(props);
        this.securityExemptions = [];
        this.state = {
            viewport: {
                width: window.innerWidth,
                height: window.innerHeight
            },
            data: [],
            show: false,
            showError: false,
            errorMsg: '',
            errorTitle: '',
            confirm: {
                body: '',
                show: false,
                id: '',
                next: null
            },
            totalDataSize: 0,
            currentPage: 1,
            statusButton: {value: 1, requested: 0, accepted: 0, implemented: 0, cancelled:0, rejected: 0}
        };
        this.where = [];
        this.sort = 'id desc';
        this.meta = { title: '', description: 'Lists and manages security exemptions' };
        this.options = {
            noDataText: 'Loading...',
            defaultSortName: 'id',
            defaultSortOrder: 'desc',
            page: 1,
            paginationShowsTotal: true,
            sizePerPage: 50,
            sizePerPageList: [10, 25, 50, 100, 250],
            onPageChange: this.onPageChange.bind(this),
            onSizePerPageList: this.onSizePerPageList.bind(this),
            onFilterChange: this.onFilterChange.bind(this),
            onSortChange: this.onSortChange.bind(this),
            selectRowProp: {
                mode: 'checkbox',
                clickToSelect: true,
                onSelect: this.handleRowSelect,
                customComponent: this.customMultiSelect.bind(this)
            },
            cellEditProp: {
                mode: 'click',
                blurToSave: true,           
                afterDeleteRow: this.onAfterDeleteRow.bind(this),
                afterSaveCell: this.onAfterSaveCell.bind(this),
                nonEditableRows: function() {
                    return this.state.data.filter(row => row.exemption_status_id != 1 ).map(row => row.id);
                  }.bind(this)
            },
            handleConfirmDeleteRow: this.customConfirm.bind(this),
            btnGroup: this.createCustomButtonGroup.bind(this),
            deleteBtn: this.createCustomDeleteButton.bind(this),
            onSearchChange: this.onSearchChange.bind(this),
            searchField: this.createCustomSearchField            
        };

        this.updateWindowDimensions = this.updateWindowDimensions.bind(this);
        this.handleShowError = this.handleShowError.bind(this);
        this.fetchSecurityExemptions = this.fetchSecurityExemptions.bind(this);
        this.handlestatusButtonChange = this.handlestatusButtonChange.bind(this);
        this.runOnce = false;
        this.passStatusButtonBack = this.passStatusButtonBack.bind(this)

        this.markets = [];
        this.serviceDomain = [];
        this.servicesList = [];
        this.servicesListDisplay = [];
        this.securityEngineerList = [];
        this.businessPriority = []        
    }

    passStatusButtonBack(status){
        let statusButton = this.state.statusButton;
        statusButton.value = status;
        this.setState({ statusButton });
        this.where.exemption_status_id = status;
        this.fetchSecurityExemptions(this.options.page, this.options.sizePerPage, this.where, this.sort);
    }    


    passMetaBack = () => {
        this.props.passMetaBack(this.meta);
    };



    createCustomButtonGroup = props => {    
            return (
                <ButtonGroup className = "my-custom-class" sizeClass = "btn-group-md">
                    {props.insertBtn}
                    {props.deleteBtn}
                    <ExemptionStatusButtons self = {this} />
                    <ToggleButtonGroupControlled statusButton = {this.state.statusButton} passStatusButtonBack = {this.passStatusButtonBack}/>
                </ButtonGroup>
            );

    };



    componentDidMount() {
        this.passMetaBack();
        this.updateWindowDimensions();
        window.addEventListener('resize', this.updateWindowDimensions);
    }

    componentWillUnmount() {
        window.removeEventListener('resize', this.updateWindowDimensions);
    }

    renderTable(tableData) {
        let insertRow = false;
        let deleteRow = false;

        return (
            <div className = "container-fluid">
                <div className = "row-fluid">
                    <BootstrapTable 
                        data = {tableData} 
                        remote 
                        search 
                        fetchInfo = {{ dataTotalSize: this.state.totalDataSize }} 
                        options = {this.options} 
                        pagination 
                        striped 
                        hover 
                        tableHeaderClass = "table-vf thead" 
                        tableContainerClass = "securityExemptions" 
                        insertRow = {insertRow} 
                        cellEdit = {this.options.cellEditProp} 
                        deleteRow = {deleteRow} 
                        selectRow = {this.options.selectRowProp} 
                        maxHeight = {this.state.viewport.height * 0.66} 
                        ref = "table"
                    >
                        <TableHeaderColumn dataField = "id" isKey = {true} editable = {false} hiddenOnInsert width = {`60px`} dataFormat = {this.exemptionsLink}>
                            ID
                        </TableHeaderColumn>
                        <TableHeaderColumn dataField = "hits" editable = {false} hiddenOnInsert width = {`50px`}>
                            Hits
                        </TableHeaderColumn>
                        <TableHeaderColumn dataField = "market" width = {`150px`} formatExtraData = {this.markets} editable = {{ type: 'select', options: { values: this.markets } }}>
                            Market
                        </TableHeaderColumn>
                        <TableHeaderColumn dataField = "service_domain" width = {`150px`} formatExtraData = {this.serviceDomain} editable = {{ type: 'select', options: { values: this.serviceDomain } }}>
                            Service Domain
                        </TableHeaderColumn>
                        <TableHeaderColumn dataField = "service_id" width = {`200px`}  editable = {false} dataFormat = {this.serviceFormatter}>
                            Service / Project / Programme
                        </TableHeaderColumn>
                        <TableHeaderColumn dataField = "demand_ref"  width = {`70px`} editable = {{ type: 'text', validator: this.isGenericName }}>
                            Demand ID
                        </TableHeaderColumn>
                        <TableHeaderColumn dataField = "summary"  width = {`200px`} editable = {false}>
                            Summary
                        </TableHeaderColumn>
                        <TableHeaderColumn dataField = "filename" width = {`200px`} dataFormat = {this.commsMatrixLink} editable = {false}>
                            Commsmatrix
                        </TableHeaderColumn>
                        <TableHeaderColumn dataField = "business_priority" width = {`100px`} formatExtraData = {this.businessPriority} editable = {{ type: 'select', options: { values: this.businessPriority } }}>
                            Priority
                        </TableHeaderColumn>
                        <TableHeaderColumn dataField = "expiry_date" width = {`150px`} editable = {true}>
                            Expiry
                        </TableHeaderColumn>
                        <TableHeaderColumn dataField = "security_engineer" width = {`200px`} dataFormat = {this.htmlFormatter} formatExtraData = {this.securityEngineerList} editable = {{ type: 'select', options: { values: this.securityEngineerList } }}>
                            Security Engineer
                        </TableHeaderColumn>
                        <TableHeaderColumn dataField = "ts_created" width = {`130px`} editable = {false} hiddenOnInsert>
                            Requested
                        </TableHeaderColumn>
                        <TableHeaderColumn dataField = "created_by" width = {`110px`} editable = {false} hiddenOnInsert>
                            Requested By
                        </TableHeaderColumn>
                    </BootstrapTable>
                </div>
            </div>
        );
    }

    render() {
        const { securityExemptions } = this.props;

        if (!this.runOnce && this.props.isReady && this.securityExemptions.length == 0) {
            this.runOnce = true;

            this.where = {exemption_status_id : this.state.statusButton.value};
            this.initData();
        }

        let table = (
            <div>
                Loading...<i className = "fa fa-spinner fa-spin" />
            </div>
        );

        if (this.state.show) {
            table = this.renderTable(this.state.data);
            this.moveElement();
        }

        return (
            <div className = "container-fluid">
                <div className = "row-fluid top-buffer">{table}</div>
                <ModalConfirm body = {this.state.confirm.body} show = {this.state.confirm.show} id = {this.state.confirm.id} handleConfirmYes = {this.handleConfirmYes} handleConfirmNo = {this.handleConfirmNo} />
                <ModalError title = {this.state.errorTitle} body = {this.state.errorMsg} show = {this.state.showError} handleCloseError = {this.handleCloseError} />
            </div>
        );
    }
}

function mapStateToProps(state) {
    return {
        securityExemptions: state.securityExemptions,
        listsReducer: state.listsReducer
    };
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators(
        {
            fetchSecurityExemptions,
            fetchSecurityExemptionsCount,
            fetchMarkets,
            fetchServiceDomains,
            fetchServicesList,
            fetchSecurityEngineerList,
            fetchBusinessPriorityList,
            updateSecurityExemption
        },
    dispatch
);

}

экспортировать соединение по умолчанию (mapStateToProps, mapDispatchToProps) (SecurityExemptions);

}

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
1 162
1

Ответы 1

Согласно документации onChange следует указывать на компоненте ToggleButtonGroup, а не на компоненте ToggleButton,

<ToggleButtonGroup
        type = "checkbox"
        value = {this.state.value}
        onChange = {this.handleChangeEvent}
      >
        <ToggleButton value = {1}>Checkbox 1 (pre-checked)</ToggleButton>
        <ToggleButton value = {2}>Checkbox 2</ToggleButton>
        <ToggleButton value = {3}>Checkbox 3 (pre-checked)</ToggleButton>
        <ToggleButton value = {4} disabled>
          Checkbox 4 (disabled)
        </ToggleButton>
</ToggleButtonGroup>

Обновлено: если это не сработает, вы всегда можете использовать,

handleClick = (e)=>{
   console.info(e.target.value)
}

<ToggleButton onClick = {this.handleClick}value = {1} className = "badge2" data-count = {this.props.statusButton.requested}>Requested</ToggleButton>

У меня есть onChange на ToggleButtonGroup, но он не работает, если type является радио.

shorif2000 04.06.2018 11:36

Вы пробовали после удаления onchange из ToggleButton ??

Rohith Murali 04.06.2018 11:37

Я добавил еще один метод

Rohith Murali 04.06.2018 14:08

@ Shortif2000 А вторым способом пробовали? с помощью onclick?

Rohith Murali 04.06.2018 14:40

Другие вопросы по теме