简体   繁体   中英

ReactJs set indeterminate state of custom bootstrap checkbox

I've made this checkbox which should be a "Three-State-Checkbox" it's using the indeterminate state not only as "visual-value" but also as a "real"-value. It work's fine if I'm only using the standard checkbox but if I use the bootstrap custom checkbox it doesn't work anymore because the ReactDOM.findDOMNode(this).indeterminate can't access the checkbox. So ReactDOM.findDOMNode(this).indeterminate = true; doesn't set indeterminate to true .

This is my component:

import React from "react";
import ReactDOM from 'react-dom';
import PropTypes from "prop-types";
import FormsStatic from "../FormsStatic";

class ThreeStateCheckbox extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            value: this.props.value || "0",
            checked: false
        }
    }
    componentDidMount() {
        if (this.state.value != "0") {
            this.state.value == "1" ? this.setState({ checked: true }) : ReactDOM.findDOMNode(this).indeterminate = true;
        }
    }

    changeCbState() {
        if (this.state.value == "0") {
            this.state.value = "1";
            this.setState({ checked: true })
            ReactDOM.findDOMNode(this).indeterminate = false;
        }
        else if (this.state.value == "1") {
            this.state.value = "2";
            this.setState({ checked: false })
            ReactDOM.findDOMNode(this).indeterminate = true;
        }
        else {
            this.state.value = "0";
            this.setState({ checked: false })
            ReactDOM.findDOMNode(this).indeterminate = false;
        }
        this.props.onChange(this.state.value);
    }
    render() {
        const uniqueId = FormsStatic.guid();
        return (
            <div className="custom-control custom-checkbox">
                <input
                    type="checkbox"
                    className="custom-control-input"
                    id={"others-" + uniqueId}
                    checked={this.state.checked}
                    onChange={() => {
                        this.changeCbState();
                    }}
                />
                <label className="custom-control-label" htmlFor={"others-" + uniqueId}>
                </label>
            </div>
        );
    }
}

ThreeStateCheckbox.propTypes = {
    className: PropTypes.string,
    value: PropTypes.string,
    onChange: PropTypes.func
}

export default ThreeStateCheckbox;

What is the way to set the indeterminate of the checkbox?

Edit: in changeCbState I can pass the access the checkbox via eventargs (ev.target) but I also need it in componentDidMount() . Still have no idea how to access it there.

Create a ref and use that to control the indeterminate in the DOM level:

constructor(props) {
    //...
    this.checkboxRef = React.createRef();
    //...
}

Then add the ref prop to your checkbox.

<input
    type="checkbox"
    ...
    ref={this.checkboxRef}
/>

Now you can use the following code to set the indeterminate sate:

this.checkboxRef.indeterminate = true

So I finally found the answer: @NonameSL answers was on the right way but I couldn't change the indeterminate state because the ref is frozen in reactjs.

My solution is to create a ref like this:

this.checkboxRef = React.createRef();

Add the ref to my checkbox:

<input
    type="checkbox"
    className="custom-control-input"
    id={"others-" + uniqueId}
    checked={this.state.checked}
    ref={this.checkboxRef}
    onChange={() => this.changeCbState()}
/>

just as @NonameSL said.

But now I can access the indeterminate state like this:

ReactDOM.findDOMNode(this.checkboxRef.current).indeterminate = true;

Here's a working solution based on this blog post .

IndeterminateCheckbox.tsx

import React, { useEffect, useRef } from 'react';
import FormCheck, { FormCheckProps } from 'react-bootstrap/FormCheck';

export enum IndeterminateCheckboxValue {
    Unchecked,
    Checked,
    Indeterminate,
}

export interface IndeterminateCheckboxProps extends FormCheckProps {
    value: IndeterminateCheckboxValue;
}

export default function IndeterminateCheckbox(props: IndeterminateCheckboxProps) {
    const { value, ...otherProps } = props
    const checkRef = useRef<HTMLInputElement>();

    useEffect(() => {
        if (checkRef.current) {
            checkRef.current.checked = value === IndeterminateCheckboxValue.Checked
            checkRef.current.indeterminate = value === IndeterminateCheckboxValue.Indeterminate
        }
    })

    return (
        <FormCheck type="checkbox" ref={checkRef} {...otherProps} />
    )
}

Usage:

<IndeterminateCheckbox value={IndeterminateCheckboxValue.Indeterminate} />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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