lundi 7 novembre 2022

Save and remember Checkbox selections to state

Two things I'm trying to accomplish:

  • Save user-selected checkboxes to state array for submission later in a multistep form, currently can do this with radio buttons (this includes an other box with a user entry)
  • Remember a user's selections so upon clicking a "previous" (already built functionality) button their previous selections remain.
'use strict';

import React, { Component } from 'react';
import Form from 'react-bootstrap/Form';
import FormCheck from 'react-bootstrap/FormCheck';
import Feedback from 'react-bootstrap/Feedback';

export default class Step3 extends Component {
  constructor(props) {

    super(props);

    this.state = {
      checkedBox: [],
      userSelected: props.getStore().userSelected,
      otherchecked: false
    };

    this.handleChange = this.handleChange.bind(this);
    this.validateOnDemand = true; // this flag enables onBlur validation as user fills forms

    this.validationCheck = this.validationCheck.bind(this);
    this.isValidated = this.isValidated.bind(this);
  }

  handleCheckboxChange = (event) =>{
    //console.log(event.target.checked);
    const isChecked = event.target.checked;
    if (isChecked) {
        this.setState({ checkedBox: [...this.state.checkedBox, event.target.value] });
       // this.setState({userSelected: this.state.checkedBox}) // attempting to store checked array in state
    } else {
        let index = this.state.checkedBox.indexOf(event.target.value);
        this.state.checkedBox.splice(index, 1);
        this.setState({checkedBox: this.state.checkedBox})
       // this.setState({checkedBox: props.getStore().userSelected}); // attempting to store checked array in state
    }


}

  handleChange() {
    this.setState({
        otherchecked: !this.state.otherchecked
    })
  }


  isValidated() {
    const userInput = this.grabUserInput(); // grab user entered vals
    console.log(this.state.checked)
    const validateNewInput = this.validateData(userInput); // run the new input against the validator
    let isDataValid = false;

    // if full validation passes then save to store and pass as valid
    if (Object.keys(validateNewInput).every((k) => { return validateNewInput[k] === true })) {
        if (this.props.getStore().selectedCheckbox != this.state.checkedBox) { // only update store of something changed
          this.props.updateStore({
            ...userInput,
            savedToCloud: false // use this to notify step4 that some changes took place and prompt the user to save again
          });  // Update store here (this is just an example, in reality you will do it via redux or flux)
        }

        isDataValid = true;
    }
    else {
        // if anything fails then update the UI validation state but NOT the UI Data State
        this.setState(Object.assign(userInput, validateNewInput, this.validationErrors(validateNewInput)));
    }

    return isDataValid;
  }

 handleOther = e => {
    this.handleCheckboxChange(e)
    this.handleChange()
  }

  validationCheck() {
    if (!this.validateOnDemand)
      return;

    const userInput = this.grabUserInput();
    console.log(userInput) // grab user entered vals
    const validateNewInput = this.validateData(userInput); // run the new input against the validator

    this.setState(Object.assign(userInput, validateNewInput, this.validationErrors(validateNewInput)));
  }

   validateData(data) {
    console.log(this.state.checkedBox.length);
    const numChoices = this.state.checkedBox.length
    return  {
      checkboxVal: (numChoices != 0)
      }
  }

  validationErrors(val) {
    const errMsgs = {
      checkboxValMsg: val.checkboxVal ? '' : 'Please make at least one selection'
    }
    return errMsgs;
  }

  grabUserInput() {
    return {
      checked: this.state.selectedCheckbox
    };
  }

Front-end Render for easier viewing

  render() {

    // explicit class assigning based on validation
    let notValidClasses = {};

        if (typeof this.state.checkboxVal == 'undefined' || this.state.checkboxVal) {
      notValidClasses.checkboxCls = 'no-error';
    }
    else {
       notValidClasses.checkboxCls = 'has-error';
       notValidClasses.checkboxValGrpCls = 'val-err-tooltip';
    }

    const otherTextBox = this.state.otherchecked
        ? <div>
          <input
            type="text"
            id="other-user-text"
            name="other"
            className="form-control"
            style=
            onChange={this.handleCheckBoxChange}
            value={this.state.text} />
        </div>
      : null;

    return (
      <div className="step step3">
        <div className="row">
          <form id="Form" className="form-horizontal">
            <legend>
              QUESTION???
            </legend>
            <div className={notValidClasses.refugeeSafetyCls}>
              <div className="checkbox-container">
                <div className="checkbox-container_column">
                  <label className="choice-contain">
                    <span>Selection 1</span>
                    <input
                      value="Selection 1"
                      name="userselected"
                      type="checkbox"
                      onChange={this.handleCheckboxChange}
                    />
                    <div className="choice-input"></div>
                  </label>
                  <label className="choice-contain">
                    <span>
                      Selection 2
                    </span>
                    <input
                      value="Selection 2"
                      name="userselected"
                      type="checkbox"
                      onChange={this.handleCheckboxChange}
                    />
                    <div className="choice-input"></div>
                  </label>
                  <label className="choice-contain">
                    <span>
                      Selection 3
                    </span>
                    <input
                      value="Selection 3"
                      name="userselected"
                      type="checkbox"
                      onChange={this.handleCheckboxChange}
                    />
                    <div className="choice-input"></div>
                  </label>
                  <label className="choice-contain">
                    <span>Other</span>
                   <input
                     value="Other"
                     name="userselected"
                     type="checkbox"
                     id="other-checkbox"
                     onChange={this.handleOther}
                   />
                  <div className="choice-input"></div>
                  </label>
                  {otherTextBox}
                  </div>
                <div className={notValidClasses.checkboxValGrpCls}>
                {this.state.checkboxValMsg}
                </div>
          </form>
        </div>
      </div>
    );
  }
}

What I've tried: I have the array of checked boxes being stored within "checkedBox" and then that being stored into userSelected with setState and props.getStore using the handler. But, when I move onto the next component and try to pull the "userSelected" values, it's pulled as empty.

Even though, pulling the "userSelected" and "checkedBox" array from this screen show that they're properly being stored.

  handleCheckboxChange = (event) =>{
    //console.log(event.target.checked);
    
    const isChecked = event.target.checked;
    if (isChecked) {
        this.setState({ checkedBox: [...this.state.checkedBox, event.target.value] });
        this.setState({userSelected: this.state.checkedBox}) // attempting to store checked array in state

    } else {
        let index = this.state.checkedBox.indexOf(event.target.value);
        this.state.checkedBox.splice(index, 1);
        this.setState({checkedBox: this.state.checkedBox})
        this.setState({checkedBox: props.getStore().userSelected}); // attempting to store checked array in state

    }



Aucun commentaire:

Enregistrer un commentaire