Home > Blockchain >  How to parent tr checked if child tr is checked
How to parent tr checked if child tr is checked

Time:07-02

I want to know if any parent-tr child-tr checkbox is checked then parent-tr also checked.

if window load the function check which parent-tr child is checkbox is true if is find any child checkbox true then the parent also checked.

function childRowCheck() {
    const list = $("#parent-tr input:checkbox").prop("checked", true);

    const childRow = $("tr.child-tr #id_ticker:checked");

    childRow.each(function (i) {
        return list[i]
    });
}
$('tbody tr.child-tr').click(':checkbox', function (e) {
    childRowCheck();
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<table>
  <tbody>
    <!-- parent -->
    <tr id="parent-tr">
      <td><input type="checkbox" name="subject" id="subject">Parent</td>
      <td colspan="3"></td>
    </tr>
    
    <!-- child -->
    <tr id="child-tr">
      <td><input type="checkbox" name="ticker" id="ticker">Child</td>
    </tr>
    
    <tr id="child-tr">
      <td><input type="checkbox" name="ticker" id="ticker">Child</td>
    </tr>
    
    <tr id="child-tr">
      <td><input type="checkbox" name="ticker" id="ticker">Child</td>
    </tr>

    <!-- parent -->
    <tr id="parent-tr">
      <td><input type="checkbox" name="subject" id="subject">Parent</td>
      <td colspan="3"></td>
    </tr>
    
    <!-- child -->
    <tr id="child-tr">
      <td><input type="checkbox" name="ticker" id="ticker">Child</td>
    </tr>
    
    <tr id="child-tr">
      <td><input type="checkbox" name="ticker" id="ticker">Child</td>
    </tr>
    
    <tr id="child-tr">
      <td><input type="checkbox" name="ticker" id="ticker">Child</td>
    </tr>
  </tbody>
</table>

CodePudding user response:

You have much better control of your application, if you control the data and not the UI:

  • create a data structure that best suits the relation(s) between the elements
  • create a template that can be re-used to populate the DOM

The main benefit of the solution below is that you always have a correct state that you can use (e.g. submit); also the shape of the data does not change: the input & output of your process look the same.

I put one more level of depth (so parent->child->grandchild) to show that it works quite nice with n levels hierarchy.

const data = [{
    id: "parent-tr-1",
    label: "Parent 1",
    checked: false,
    children: [{
        id: "child-tr-1-1",
        label: "Child 1_1",
        checked: false,
        children: [
          {
            id: "child-tr-1-1-1",
            label: "Child 1_1_1",
            checked: false,
            children: [],
          },
          {
            id: "child-tr-1-1-2",
            label: "Child 1_1_2",
            checked: false,
            children: [],
          }
        ],
      },
      {
        id: "child-tr-1-2",
        label: "Child 1_2",
        checked: false,
        children: [],
      },
    ]
  },
  {
    id: "parent-tr-2",
    label: "Parent 2",
    checked: false,
    children: [{
        id: "child-tr-2-1",
        label: "Child 2_1",
        checked: false,
        children: [],
      },
      {
        id: "child-tr-2-2",
        label: "Child 2_2",
        checked: false,
        children: [],
      },
      {
        id: "child-tr-2-3",
        label: "Child 2_3",
        checked: false,
        children: [],
      },
    ]
  },
]

const getRowsFlat = (data) => data.reduce((a, c) => [...a, c, ...getRowsFlat(c.children)], [])

const setChecked = (id, data, checkedState) => {
  data.forEach(e => {
    // setting children checked if parent is clicked
    if (e.id === id || id === "parent-force") {
      e.checked = checkedState ?? !e.checked
      if (e.id === id) {
        setChecked("parent-force", e.children, e.checked)
      } else {
        setChecked("parent-force", e.children)
      }
    } else {
      setChecked(id, e.children)
    }

    // if ANY of the children is set to checked, parent should be checked
    if (e.children.length && e.children.some(({
        checked
      }) => checked)) {
      e.checked = true
    }

    // if NONE of the children is set to checked, parent should not be checked
    if (e.children.length && e.children.every(({
        checked
      }) => !checked)) {
      e.checked = false
    }
  })
}

// row HTML template
const getRowHtml = (data) => {
  return `
    <tr>
      <td>
        <input type="checkbox" id="${data.id}" ${ data.checked ? "checked" : null }/>
        <label for="${data.id}">${data.label}</label>
      </td>
    </tr>
  `
}

// table update function
const updateContainer = (container) => (data) => {
  container.innerHTML = data.map(getRowHtml).join("")
}

// initialization
const tbody = document.getElementById("tbody")
const updateTableBody = updateContainer(tbody)
// first render
setChecked(null, data) // if run with id NULL, then only the children can affect the parent
updateTableBody(getRowsFlat(data))

jQuery(document).ready(function($) {
  $("#table").on("click", "input", function() {
    const thisId = $(this).attr("id")
    setChecked(thisId, data)
    updateTableBody(getRowsFlat(data))
  })
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<table id="table">
  <tbody id="tbody"></tbody>
</table>

CodePudding user response:

You can not use the same id multiple times.

Check following code with class instead of id:

 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<table>
  <tbody>
    <!-- parent -->
    <tr>
      <td>
        <input type="checkbox" name="subject"  />Parent
      </td>
      <td colspan="3"></td>
    </tr>

    <!-- child -->
    <tr>
      <td><input type="checkbox" name="ticker"  />Child</td>
    </tr>

    <tr>
      <td><input type="checkbox" name="ticker"  />Child</td>
    </tr>

    <tr>
      <td><input type="checkbox" name="ticker"  />Child</td>
    </tr>

    <!-- parent -->
    <tr>
      <td>
        <input type="checkbox" name="subject"  />Parent
      </td>
      <td colspan="3"></td>
    </tr>

    <!-- child -->
    <tr>
      <td><input type="checkbox" name="ticker"  />Child</td>
    </tr>

    <tr>
      <td><input type="checkbox" name="ticker"  />Child</td>
    </tr>

    <tr>
      <td><input type="checkbox" name="ticker"  />Child</td>
    </tr>
  </tbody>
</table>

<script>
  $(document).ready(function () {
    $(".ticker1").click(function () {
      if ($(this).is(":checked")) {
        $(".subject1").prop("checked", true);
      } else {
        $(".subject1").prop("checked", false);
      }
    });
    $(".ticker2").click(function () {
      if ($(this).is(":checked")) {
        $(".subject2").prop("checked", true);
      } else {
        $(".subject2").prop("checked", false);
      }
    });
    
  });
</script>

Here I modified the code by changing ids to classes and made other necessary changes.

  • Related