Answer the question
In order to leave comments, you need to log in
How to competently make 3 states of a checkbox in an Angular filter?
Good day.
Faced with rather difficult task for the level of knowledge.
I am working with a project on Angular, more in terms of layout. I'm not familiar with TS, but I can figure it out with an example.
The site has a filter with 3 levels of nesting:
- Level 1
- Level 2
- Level 2
- Level 3
- Level 3
- Level 3
- Level 2
If one of the items on the 3rd level is checked, the checkboxes of the 2nd and 1st levels were marked as indeterminate (3rd state), respectively, at the 2nd level it is similar. If all checkboxes are checked at this level (state 2), the checkbox of the parent checkbox on the level above is also checked and removed if it is cleared at the level below.
In layout on jq, there were no problems with the implementation, well, maybe a little crooked.
JQ
$(document).ready(function () {
$('.b-filterItem_bvar').on('click', '.cbx-label', function () {
// Вложенность 3-го уровня
if ($(this).closest('.b-filterItem').hasClass('fi_b-dropdown')) {
var f_filterItem = $(this).closest('.b-filterItem'),
f_filterItemHead = f_filterItem.find('.b-filterItem_head.checkGroup'),
f_filterItemCount = f_filterItem.find('.bvar_dropdown').find('.cbx-input').length,
f_filterItem_cheked = f_filterItem.find('.bvar_dropdown').find('.cbx-input:checked').length;
if (f_filterItemCount === f_filterItem_cheked) {
// Отмечены все чекбоксы
f_filterItemHead.find('.cbx-label').addClass('checked');
f_filterItemHead.find('.cbx-input').attr("checked", "checked");
if (f_filterItemHead.find('.cbx__checkMark').hasClass('noAllChecked')) {
f_filterItemHead.find('.cbx__checkMark').removeClass('noAllChecked');
}
} else if (f_filterItem_cheked === 0) {
// Не отмечены чекбоксы
f_filterItemHead.find('.cbx-label').removeClass('checked');
f_filterItemHead.find('.cbx-input').removeAttr("checked", "checked");
if (f_filterItemHead.find('.cbx__checkMark').hasClass('noAllChecked')) {
f_filterItemHead.find('.cbx__checkMark').removeClass('noAllChecked');
}
} else if (f_filterItemCount !== f_filterItem_cheked & f_filterItem_cheked !== 0) {
// Отмечены некоторые чекбоксы
f_filterItemHead.find('.cbx-label').removeClass('checked');
f_filterItemHead.find('.cbx-input').removeAttr("checked", "checked");
f_filterItemHead.find('.cbx__checkMark').addClass('noAllChecked');
}
}
// Замена чекбокса родительской группы
var f_cbxBvar = $(this).closest('.b-filterItem_bvar'),
f_itemBodyHead = $(this).closest('.b-filterItem_body').prev('.b-filterItem_head '),
f_cbxBvarCount = f_cbxBvar.find('.cbx-input').length,
f_cbxBvarCount_cheked = f_cbxBvar.find('.cbx-input:checked').length;
if (f_cbxBvarCount === f_cbxBvarCount_cheked) {
f_itemBodyHead.find('.cbx__checkMark').removeClass('noAllChecked');
f_itemBodyHead.find('.cbx-label').addClass('checked');
f_itemBodyHead.find('.cbx-input').attr("checked", "checked");
} else if (f_cbxBvarCount_cheked === 0) {
f_itemBodyHead.find('.cbx__checkMark').removeClass('noAllChecked');
f_itemBodyHead.find('.cbx-label').removeClass('checked');
f_itemBodyHead.find('.cbx-input').removeAttr("checked", "checked");
} else if (f_cbxBvarCount !== f_cbxBvarCount_cheked) {
f_itemBodyHead.find('.cbx__checkMark').addClass('noAllChecked');
f_itemBodyHead.find('.cbx-label').removeClass('checked');
f_itemBodyHead.find('.cbx-input').removeAttr("checked", "checked");
}
});
});
<div class="b-filterItem dropdown open">
<!-- 1 уровень -->
<div class="b-filterItem_head checkGroup">
<div class="cbx">
<div class="cbx-label">
<input class="cbx-input" id="letters_cbx_1" type="checkbox" name="" value="">
<div class="cbx__box"></div>
<div class="cbx__checkMark"></div>
</div>
</div>
<div class="b-filterItem_title">
<span class="b-filterItem_arrow f_chO"></span>
<span class="b-filterItem_name text-overflow">Типы</span>
</div>
</div>
<div class="b-filterItem_body f_chB">
<div class="b-filterItem_bvar">
<!-- 2 уровень -->
<div class="b-filterItem">
<div class="b-filterItem_head">
<div class="cbx">
<div class="cbx-label">
<input class="cbx-input" type="checkbox" name="">
<div class="cbx__box"></div>
<div class="cbx__checkMark"></div>
</div>
</div>
<div class="b-filterItem_bvar-title text-overflow">
<span class="text-overflow">Аккаунт</span>
</div>
</div>
<div class="bvar_dropdown f_chB" style="display: none;">
<!-- 3 уровень -->
<div class="bvar_dropdown-item">
<div class="app-spacer"></div>
<div class="cbx-label">
<div class="cbx">
<input class="cbx-input" type="checkbox" name="">
<div class="cbx__box"></div>
<div class="cbx__checkMark"></div>
</div>
<div class="bvar_dropdown-label">
<span class="bvar_dropdown-title text-overflow">
<span class="text-overflow">Facetime аудио</span>
</span>
</div>
</div>
</div>
<!-- 3 уровень -->
<!-- 3 уровень -->
</div>
</div>
<!-- 2 уровень -->
<!-- 2 уровень -->
</div>
</div>
<!-- 1 уровень -->
<!-- 1 уровень -->
</div>
&__box:before,
&__box:after {
content: "";
position: absolute;
width: 16px;
height: 16px;
border-radius: $borderRadius;
top: 3px;
left: 0;
}
&__box:before {
border: 2px solid $greyCbxColor;
background: transparent;
}
&__box:after,
&__box.indeterminate:after {
background: $blueColor url('../assets/icons/svg/icon-checked.svg') no-repeat center;
background-size: 80%;
color: #fff;
opacity: 0;
}
input[type="checkbox"]:checked ~ &__box:after {
opacity: 1;
}
input[type="checkbox"]:indeterminate ~ &__box:after {
opacity: 1;
background: $blueColor url('../assets/icons/svg/icon--indeterminate-wite.svg') no-repeat center;
}
input[type="checkbox"],
&-input {
position: absolute;
width: 16px;
height: 16px;
margin: 0;
top: 3px;
opacity: 0;
z-index: 1;
}
Answer the question
In order to leave comments, you need to log in
You create a structure like this:
{
"value": 1,
"isSelected": true,
"allChildsSelected": true,
"childs": [
{
"isSelected": true,
"value": 2,
"allChildsSelected": true,
"childs": [
{
"value": 3,
"allChildsSelected": true,
"isSelected": true,
"childs": null
}
]
},
{
"value": 5,
"allChildsSelected": true,
"childs": null,
"isSelected": true
}
]
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question