@Matthew06

Как исправить ошибку с неработающими родительскими и дочерними checkbox?

Я разрабатываю сайт на django и столкнулся с проблемой с checkbox. С помощью jinja я передаю в html файл два списка. Один просто строковый список (organ_set_sort). Это список с названиями групп, на который делится второй список. Другой - список пар строк [str,str] - tissue_set_sort. В tissue_set_sort первое значение - собственное название элемента, а второе - название группы, к которой он принадлежит (из списка organ_set_sort).

Для каждого элемента из обоих списков я делаю свой checkbox, которые группирую по divам. Важно, что чекбоксы organ_set_sort и tissue_set_sort находятся в разных div. Мне нужно, чтобы при отметке родительского чекбокса все его дочерние тоже становились отмеченными. Соответственно при снятии отметки - аналогично. Также хотелось бы, чтобы при снятии всех дочерних checkbox - родительский тоже снимался.

Мой код :

<div class="content_organ">
            <label><h4>Organe_name</h4></label>
            <!--<input type="text" name="organe">-->
            <br>
            {% for o in organ_set_sort %}
            <!--o = o.filter(question = qu.id) -->
            <label><input type="checkbox" name={{o}} value={{o}} id={{o}} onchange="toggleChildren({{o}})">{{o}}</label>
            <br>
            {% endfor %}
        </div>
        <div class="content_tissue">
            <label><h4>Tissue_name</h4></label>
            <!--        <input type="text"  name="tissue">-->
            {% for t in tissue_set_sort %}
            <!--o = o.filter(question = qu.id) -->
            <label><input type="checkbox" name={{t.0}} value={{t.0}} id={{t.1}} onchange="checkParent({{t.1}})">{{t.0}}</label>
            <br>
            <br>
            {% endfor %}
        </div>
<script>
var submitButton = document.getElementById('submit_1');
    if(submitButton){
    submitButton.addEventListener('click', function(event) {
        this.disabled = true;
    });
    }
    function toggleChildren(parentId){
    const parentCheckbox=document.getElementById(parentId);
    const childCheckboxes=document.getElementById(parentId+'_').querySelectorAll('input[type="checkbox"]');

    childCheckboxes.forEach(child => {
        child.checked = parentCheckbox.checked;
    });
}
function checkParent(parentId) {
    const parentCheckbox = document.getElementById(parentId);
    const childCheckboxes = document.getElementById(parentId+'_').querySelectorAll('input[type="checkbox"]');

    // Проверяем, все ли дочерние чекбоксы сняты
    const allUnchecked = Array.from(childCheckboxes).every(child => !child.checked);

    // Если все дочерние чекбоксы сняты, снимаем галочку у родительского
    parentCheckbox.checked = !allUnchecked;
}
</script>


Однако при нажатии на родительский checkbox в просмотре кода получаю следующую ошибку.

Uncaught TypeError: Cannot read properties of null (reading 'querySelectorAll')

Заранее спасибо!

UPD:
Обнаружилась ещё одна проблема - если parentId имеет в название знак "-" (например - adipose-subcutaneous, то выводится ошибка (index):291 Uncaught ReferenceError: adipose is not defined at HTMLInputElement.onchange. Т.е. он не считывает все, что после тире.

UPD2:
Исправил , заменив тире на нижнее подчеркивание
  • Вопрос задан
  • 79 просмотров
Решения вопроса 2
alexey-m-ukolov
@alexey-m-ukolov Куратор тега JavaScript
Во-первых, вы пытаетесь искать дочерние чекбоксы внутри родительского элемента. Их, естественно, там быть не может.
Во-вторых, вы зачем-то прибавляете к id _ и элемент не находится.

Вам нужно дочерним чекбоксам добавить data-атрибут с id родителя и работать с ним - при смене состояния родителя искать все элементы, где его id указан в data-атрибуте (через обычный querySelectorAll на документе), при смене состояния ребёнка искать родителя по значению из data-атрибута.
Ответ написан
@Matthew06 Автор вопроса
Итоговый (рабочий) вариант.

<script>
    var submitButton = document.getElementById('submit_1');
    if(submitButton){
    submitButton.addEventListener('click', function(event) {
        this.disabled = true;
    });
    }
    function toggleChildren(parentId){
    const parentCheckbox=document.getElementById(parentId);
    const childCheckboxes=document.querySelectorAll(`input[type="checkbox"][data-parent=${parentId}]`);

    childCheckboxes.forEach(child => {
        child.checked = parentCheckbox.checked;
    });
}
function checkParent(parentId) {
    const parentCheckbox = document.getElementById(parentId);
    const childCheckboxes = document.querySelectorAll(`input[type="checkbox"][data-parent=${parentId}]`);

    // Проверяем, все ли дочерние чекбоксы сняты
    const allUnchecked = Array.from(childCheckboxes).every(child => !child.checked);

    // Если все дочерние чекбоксы сняты, снимаем галочку у родительского
    parentCheckbox.checked = !allUnchecked;
}
</script>

<div class="second_line">
        <div class="content_organ">
            <label><h4>Organe_name</h4></label>
            <!--<input type="text" name="organe">-->
            <br>
            {% for o in organ_set_sort %}
            <!--o = o.filter(question = qu.id) -->
            <label><input type="checkbox" name={{o}} value={{o}} id="{{o}}" onchange="toggleChildren('{{o}}')">{{o}}</label>
            <br>
            {% endfor %}
        </div>
        <div class="content_tissue">
            <label><h4>Tissue_name</h4></label>
            <!--        <input type="text"  name="tissue">-->
            {% for t in tissue_set_sort %}
            <!--o = o.filter(question = qu.id) -->
            <label><input type="checkbox" name={{t.0}} value={{t.0}} data-parent="{{t.1}}" onchange="checkParent('{{t.1}}')">{{t.0}}</label>
            <br>
            <br>
            {% endfor %}
        </div>
    </div>


Отдельное спасибо Алексей Уколов за помощь. Обязательно почитаю!
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы