Skip to content

Commit

Permalink
refactor: group listeners
Browse files Browse the repository at this point in the history
  • Loading branch information
nijmra committed Oct 23, 2024
1 parent 0735be1 commit 37532a8
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 36 deletions.
2 changes: 2 additions & 0 deletions odpc.client/src/components/checkbox-group/CheckboxGroup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
@click="toggleAll"
:checked="allSelected"
:aria-describedby="`description-${instanceId}`"
:aria-invalid="!model.length ? true : undefined"
/>
selecteer alles
</label>
Expand All @@ -28,6 +29,7 @@
:value="uuid"
v-model="model"
:aria-describedby="`description-${instanceId}`"
:aria-invalid="!model.length ? true : undefined"
/>{{ naam }}</label
>
</div>
Expand Down
59 changes: 23 additions & 36 deletions odpc.client/src/components/checkbox-group/use-checkbox-group.ts
Original file line number Diff line number Diff line change
@@ -1,56 +1,43 @@
import { ref, onUnmounted, watchEffect } from "vue";
import { ref, watchEffect, onUnmounted } from "vue";

export const useCheckboxGroup = () => {
const groupRef = ref<HTMLElement>();

const isAnyChecked = (checkboxes: NodeListOf<HTMLInputElement>) =>
Array.from(checkboxes).some((checkbox) => checkbox.checked);

const onCheckboxChange = (checkboxes: NodeListOf<HTMLInputElement>) =>
!isAnyChecked(checkboxes)
? setCustomValidityCheckboxGroup(checkboxes)
: clearCustomValidityCheckboxGroup(checkboxes);
const setCustomValidityCheckboxGroup = () => {
const checkboxes = (groupRef.value?.querySelectorAll("[type='checkbox']") ||
[]) as NodeListOf<HTMLInputElement>;

const setCustomValidityCheckboxGroup = (checkboxes: NodeListOf<HTMLInputElement>) =>
checkboxes.forEach((checkbox) => checkbox.setCustomValidity("Kies minimaal één optie."));

const clearCustomValidityCheckboxGroup = (checkboxes: NodeListOf<HTMLInputElement>) =>
checkboxes.forEach((checkbox) => checkbox.setCustomValidity(""));

const checkboxListeners: (() => void)[] = [];

const removeCheckboxListeners = () => checkboxListeners.forEach((remove) => remove());
checkboxes.forEach((checkbox) =>
checkbox.setCustomValidity(!isAnyChecked(checkboxes) ? "Kies minimaal één optie." : "")
);
};

const addCheckboxListeners = () => {
removeCheckboxListeners();
const invalidHandler = () =>
groupRef.value instanceof HTMLDetailsElement && (groupRef.value.open = true);

const addListeners = () => {
if (!groupRef.value || !groupRef.value.hasAttribute("aria-required")) return;

const checkboxes = groupRef.value.querySelectorAll(
"[type='checkbox']"
) as NodeListOf<HTMLInputElement>;

if (!checkboxes?.length) return;
setCustomValidityCheckboxGroup();

if (!isAnyChecked(checkboxes)) setCustomValidityCheckboxGroup(checkboxes);

const invalidHandler = () =>
groupRef.value instanceof HTMLDetailsElement && (groupRef.value.open = true);

const changeHandler = () => onCheckboxChange(checkboxes);

checkboxes.forEach((checkbox) => {
checkbox.addEventListener("invalid", invalidHandler);
checkboxListeners.push(() => checkbox.removeEventListener("invalid", invalidHandler));
groupRef.value.addEventListener("change", setCustomValidityCheckboxGroup);
groupRef.value.addEventListener("invalid", invalidHandler, true);
};

checkbox.addEventListener("change", changeHandler);
checkboxListeners.push(() => checkbox.removeEventListener("change", changeHandler));
});
const removeListeners = () => {
groupRef.value?.removeEventListener("change", setCustomValidityCheckboxGroup);
groupRef.value?.removeEventListener("invalid", invalidHandler, true);
};

watchEffect(() => groupRef.value && addCheckboxListeners());
watchEffect(() => {
removeListeners();
addListeners();
});

onUnmounted(() => removeCheckboxListeners());
onUnmounted(() => removeListeners());

return {
groupRef
Expand Down

0 comments on commit 37532a8

Please sign in to comment.