osori
osori

Reputation: 67

How to check/uncheck the checkbox and show in textarea?

The checked value appears in text area.

If I check more than two, I want to add the value to the newline. If I uncheck, I want to make the value disappear. If I check all, I want to add all values

I hope it works like the uploaded picture. Thanks for your help.

    <textarea rows="8" name="mobile" class="form-control" id="mobile" placeholder=""></textarea>
            <div class="custom-control custom-checkbox">
                <input type="checkbox" class="custom-control-input" id="customCheck1">
                <label class="custom-control-label" for="customCheck1" value="">all</label>
            </div>
            <div class="custom-control custom-checkbox">
                <input type="checkbox" class="custom-control-input" value="1" id="customCheck2">
                <label class="custom-control-label" for="customCheck2">1</label>
            </div>
            <div class="custom-control custom-checkbox">
                <input type="checkbox" class="custom-control-input" value="2" id="customCheck3">
                <label class="custom-control-label" for="customCheck3">2</label>
            </div>
            <div class="custom-control custom-checkbox">
                <input type="checkbox" class="custom-control-input"  value="3" id="customCheck4">
                <label class="custom-control-label" for="customCheck4">3</label>
            </div>
                <script>
                    var radio = document.querySelectorAll(".custom-control-input");
                    var mobile = document.getElementById("mobile");
                    function checkBox(e){
                    mobile.value = e.target.value;
                    }
                    radio.forEach(check => {
                    check.addEventListener("click", checkBox);
                    });
                </script>

enter image description here

Upvotes: 1

Views: 259

Answers (3)

zer00ne
zer00ne

Reputation: 44088

Update

For some reason I failed to get the OP's request correctly. I thought the output was supposed to be the sum of all checked values not a list of each checked values. I have modified the example so it can display both ways. The last expression is the only thing needing to change:

   /*
   use `sum` if you want to display the sum of all values.
   use `str` if you want to display each number on it's own line.
   */
  IO.mobile.value = str;
  • Wrap <form> around everything.
  • Assign a class to the All checkbox and then a different one to the rest of the checkboxes to share. In the example below it's: .all and .chx.
  • Add the event handler to the <form> so that any "change" events happen on or within <form> are captured.
  • Design the event handler to react to only specific tags and ignore the rest. See event delegation.

The example stores an array of values and uses various Array methods to add, remove, and calculate the numbers within it. The details are commented in the example.

// This is <form>
const form = document.forms[0];
// Initialize all and sum
let all = [];
let sum = 0;
// Define helper functions
const getSum = (x, y) => x + y;
const getStr = array => array.flat(Infinity).join('\n');

// Pass the event object
const chxSum = event => {
  /*
  This is all form controls of <form>
  ie <textarea>, and all <input>
  */
  const IO = event.currentTarget.elements;
  // This is the tag the user clicked
  const clicked = event.target;
  // This is the value of clicked as a real number
  let valNum = Number(clicked.value);
  // This is a NodeList of all .chx as an array
  const allChx = [...document.querySelectorAll('.chx')];
  /*
  if the tag that the user clicked has class .chx...
  */
  if (clicked.matches('.chx')) {
    /*
    ...see if it's checked -- if it is then
    add it's value into the all array...
    */
    if (clicked.checked) {
      all.push(valNum);
      //...otherwise remove the value from all array
    } else {
      all.splice(all.indexOf(valNum), 1);
    }
    /*
    But if the clicked tag has class .all...
    */
  } else if (clicked.matches('.all')) {
    /*
    ...see if it's clicked and if it is then check all
    of the .chx and reset the all array to [1, 2, 3]...
    */
    if (clicked.checked) {
      allChx.forEach(chx => chx.checked = true);
      all.length = 0;
      all = [1, 2, 3];
      /*
        ...otherwise uncheck all .chx and empty the all array
      */
    } else {
      allChx.forEach(chx => chx.checked = false);
      all.length = 0;
    }
    // end this function if clicked was anything else
  } else {
    return false;
  }
  // Convert the array to a string  
  let str = getStr(all);
  // Get the sum of all values in all array
  sum = all.reduce(getSum, 0);
  // Display sum in <textarea>
  /*
  use `sum` if you want to display the sum of all values.
  use `str` if you want to display each number on it's own line.
  */
  IO.mobile.value = str;
};

/*
Add event handler on <form>. 
if any changes are detected on or
within the <form> it will be captured
*/
form.onchange = chxSum;
.orA.orA {
  padding-top: 20vh;
}

.orB.orB {
  margin-left: -25vw;
}

#mobile {
  min-height: 100px;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <title></title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
  <style></style>
</head>

<body>
  <main class="container">
    <form class='row orA'>
      <fieldset class="col">
        <textarea id="mobile" name="mobile" class="form" placeholder=""></textarea>
      </fieldset>
      <fieldset class="col orB">
        <div class="form-check">
          <input id="customCheck1" class="form-check-input all" type="checkbox">
          <label for="customCheck1" class="form-check-label">All</label>
        </div>
        <div class="form-check">
          <input id="customCheck2" class="form-check-input chx" type="checkbox" value="1">
          <label for="customCheck2" class="form-check-label">1</label>
        </div>
        <div class="form-check">
          <input id="customCheck3" class="form-check-input chx" type="checkbox" value="2">
          <label for="customCheck3" class="form-check-label">2</label>
        </div>
        <div class="form-check">
          <input id="customCheck4" class="form-check-input chx" type="checkbox" value="3">
          <label for="customCheck4" class="form-check-label">3</label>
        </div>
      </fieldset>
    </form>
  </main>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>

</body>

</html>

Upvotes: 1

amlxv
amlxv

Reputation: 2005

<script>
  var radio = document.querySelectorAll('.custom-control-input');
  var mobile = document.getElementById('mobile');

  function checkBox(e) {
    var str = mobile.value;

    if (e === undefined) return;

    if (e.target.value === 'on') return selectAll();

    if (str.includes(e.target.value))
      return (mobile.value = str
        .split('\n')
        .filter((n) => n.indexOf(e.target.value) == -1)
        .join('\n'));

    mobile.value = str + e.target.value + '\n';
  }

  function selectAll() {
    for (var i = 1; i < radio.length; i++) {
      radio[i].click();
    }
    checkBox();
  }

  radio.forEach((check) => {
    check.addEventListener('click', checkBox);
  });
</script>

Refs: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox

Upvotes: 1

Jonathon Hibbard
Jonathon Hibbard

Reputation: 1546

While it may sound like a bit of overkill, I would handle this with an Array or Object instead of trying to manage it in your textarea. I'd then make sure the textarea contains only the data in whatever you choose..

For example:

const selectedDataMap = {};
const radio = document.querySelectorAll(".custom-control-input");
const mobile = document.getElementById("mobile");

const checkBox = (e) => {
    if (!selectedDataMap[e.target.id]) {
        selectedDataMap[e.target.id] = true;
    }

    selectedDataMap[e.target.id] = e.target.checked;

    mobile.value = Object.keys(selectedDataMap).filter(id => { 
        const checkboxVal = document.querySelector(id).value || 'all';
        return selectedDataMap[id] === true ? checkboxVal : '';
    }).join("\n");
};

radio.forEach(check => check.addEventListener("click", checkBox));

DISCLAIMER: The above is untested. There are literally thousands of ways of improving upon this too. After all - it's only supposed to be an example.

The point though by doing this is because you can track/control what's in an array or object map a lot easier than trying to sort line-by-line through text and all that...

You could also expand your original solution too by creating a data object (something like : [{ id: 'customCheck1", value: "", label: "all", checked: false}...]) and then print out all your checkboxes based on this object. You could then easily track your checked/unchecked by flipping the flag and then just printing out all the values in the text box. Like I said earlier though - literally thousands of ways to do this =]

Use whatever you think works best though! Good luck!

Upvotes: 1

Related Questions