3

I'm using a document structure like this

render() {
return (
    <div className="MyComponent">
        <ul className="">
            {parseRecommendations(this.props.recommendations)}
        </ul>
    </div>
);
}

function parseRecomendations(recommendations) {
    return recommendations.map((recommendation, key) => {
        return (<Recommendation data={recommendation} key={key} />);
    });
}

Where each Recommendation is its own component containing a checkbox

class Recommendation extends Component {
    const recommendation = this.props.data;
    const pageUrl = recommendation.url;

    return (
        <li className="article-item" key={key}>
            <div className="article-info">
                <input type="checkbox" defaultChecked="checked" aria-described-by={recommendation.pii} />
                <a className="journal-title" href={pageUrl} id={recommendation.pii}>{recommendation.title}</a>
            </div>
        </li>
    );

I'd like to have a title saying [Download (x) PDFs], where x is the number of selected checkboxes. How do I find the value of x in this case?

3 Answers 3

6

You need to store information about whether input is "checked" in your data. Then, simply count items with truthy "checked" flag.

Here is my solution. You should be able to get principle here and modify your code.

const data = [
    { checked: false, value: 'document 1' },
    { checked: true, value: 'document 2' },
    { checked: true, value: 'document 3' },
    { checked: false, value: 'document 4' },
    { checked: false, value: 'document 5' },
];

const Item = props => (
    <div>
        <input type="checkbox" checked={props.checked} onChange={props.onCheckChange} />
        { props.value }
    </div>
)
var Hello = React.createClass({
    getInitialState() {
        return {
            items: this.props.items.concat(),
        };
    },

    onCheckChange(idx) {
        return () => {
            const items = this.state.items.concat();
            items[idx].checked = !items[idx].checked;
            this.setState({items});
        }
    },

    totalChecked() {
        return this.state.items.filter(props => props.checked).length;
    },

  render() {
    return (
            <div>
                { this.state.items.map((props, idx) => (
                    <Item {...props} key={idx} onCheckChange={this.onCheckChange(idx)} />
                )) }
                Total checked: { this.totalChecked() }
            </div>
        );
  }
});

ReactDOM.render(
  <Hello items={data} />,
  document.getElementById('container')
);
Sign up to request clarification or add additional context in comments.

2 Comments

Instead of counting them up a tally count be maintained within onCheckChange and stored in state. Might not be ideal, but is a viable alternative.
The less state you maintain, the better. Counting total is not expensive. Personally, would not store it in state. On the other hand, I agree with you. In certain cases it's wise to cache results of some operations.
2

If you just want to get the number of selected check-boxes you can try this

let checkedBoxes = document.querySelectorAll('input[name=chkBox]:checked');

Then get the total checked boxes via checkedBoxes.length

Edit:

Instead of querying whole document. You can get the nearest possible parent via getElementsByClassName or getElementById and then apply querySelectorAll on that element.

e.g

let elem = document.getElementsByClassName("MyComponent");

let checkedBoxes = elem.querySelectorAll('input[name=chkBox]:checked');

1 Comment

Providing such answer, please, at least advise OP to apply scope - not to query document.
0

You also could obtain the total of selected checkboxes by element type. The "console.log(totalSelectedCheckboxes)" will print them when the state of totalSelectedCheckboxes change using useEffect Hook.

import React, { useState, useEffect } from 'react';

const RenderCheckboxes = () => {
    const [totalSelectedCheckboxes, setTotalSelectedCheckboxes] = useState(0);
    function handleChk() {
        setTotalSelectedCheckboxes(document.querySelectorAll('input[type=checkbox]:checked').length);
    }
    useEffect(() => {
        console.log(totalSelectedCheckboxes);
    }, [totalSelectedCheckboxes]);
    return (<div>
        <div>
            <input type="checkbox" value={1} onChange={() => handleChk()} />Chk1
        </div>
        <div>
            <input type="checkbox" value={2} onChange={() => handleChk()} />Chk2
        </div>
        <div>
            <input type="checkbox" value={2} onChange={() => handleChk()} />Chk2
        </div>
    </div>);
}
export default RenderCheckboxes;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.