Fix not being able to close groups (#11437)

* fix not being able to close groups

* search top most level checkboxes

* Fix casing of file name

Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>
This commit is contained in:
Nitwel
2022-04-12 01:15:12 +02:00
committed by GitHub
parent 38c24e5a58
commit cf56ff0e0a
3 changed files with 121 additions and 43 deletions

View File

@@ -0,0 +1,56 @@
import { computed, Ref } from 'vue';
export function useVisibleChildren(
search: Ref<string>,
modelValue: Ref<(string | number)[]>,
children: Ref<Record<string, any>[]>,
showSelectionOnly: Ref<boolean>,
itemText: Ref<string>,
itemValue: Ref<string>,
itemChildren: Ref<string>,
parentValue: Ref<string | number>,
value: Ref<string | number>
) {
const visibleChildrenValues = computed(() => {
let options = children.value || [];
if (search.value) {
options = options.filter(
(child) =>
child[itemText.value].toLowerCase().includes(search.value.toLowerCase()) ||
childrenHaveSearchMatch(child[itemChildren.value])
);
}
if (showSelectionOnly.value) {
options = options.filter(
(child) =>
modelValue.value.includes(child[itemValue.value]) ||
childrenHaveValueMatch(child[itemChildren.value]) ||
modelValue.value.includes(parentValue.value) ||
modelValue.value.includes(value.value)
);
}
return options.map((child) => child[itemValue.value]);
function childrenHaveSearchMatch(children: Record<string, any>[] | undefined): boolean {
if (!children) return false;
return children.some(
(child) =>
child[itemText.value].toLowerCase().includes(search.value.toLowerCase()) ||
childrenHaveSearchMatch(child[itemChildren.value])
);
}
function childrenHaveValueMatch(children: Record<string, any>[] | undefined): boolean {
if (!children) return false;
return children.some(
(child) =>
modelValue.value.includes(child[itemValue.value]) || childrenHaveValueMatch(child[itemChildren.value])
);
}
});
return { visibleChildrenValues };
}

View File

@@ -41,8 +41,9 @@
</template>
<script lang="ts">
import { defineComponent, computed, PropType } from 'vue';
import { defineComponent, computed, PropType, toRefs } from 'vue';
import { difference } from 'lodash';
import { useVisibleChildren } from './use-visible-children';
type Delta = {
added?: (number | string)[];
@@ -111,46 +112,20 @@ export default defineComponent({
},
emits: ['update:modelValue'],
setup(props, { emit }) {
const visibleChildrenValues = computed(() => {
let options = props.children || [];
const { search, modelValue, children, showSelectionOnly, itemText, itemValue, itemChildren, parentValue, value } =
toRefs(props);
if (props.search) {
options = options.filter(
(child) =>
child[props.itemText].toLowerCase().includes(props.search.toLowerCase()) ||
childrenHaveSearchMatch(child[props.itemChildren])
);
}
if (props.showSelectionOnly) {
options = options.filter(
(child) =>
props.modelValue.includes(child[props.itemValue]) ||
childrenHaveValueMatch(child[props.itemChildren]) ||
props.modelValue.includes(props.parentValue) ||
props.modelValue.includes(props.value)
);
}
return options.map((child) => child[props.itemValue]);
function childrenHaveSearchMatch(children: Record<string, any>[] | undefined): boolean {
if (!children) return false;
return children.some(
(child) =>
child[props.itemText].toLowerCase().includes(props.search.toLowerCase()) ||
childrenHaveSearchMatch(child[props.itemChildren])
);
}
function childrenHaveValueMatch(children: Record<string, any>[] | undefined): boolean {
if (!children) return false;
return children.some(
(child) =>
props.modelValue.includes(child[props.itemValue]) || childrenHaveValueMatch(child[props.itemChildren])
);
}
});
const { visibleChildrenValues } = useVisibleChildren(
search,
modelValue,
children,
showSelectionOnly,
itemText,
itemValue,
itemChildren,
parentValue,
value
);
const groupShown = computed(() => {
if (props.showSelectionOnly === true && props.modelValue.includes(props.value)) {
@@ -165,7 +140,7 @@ export default defineComponent({
return visibleChildrenValues.value.length > 0;
}
return typeof props.search === 'string' && props.search.length > 0;
return false;
});
const childrenValues = computed(() => props.children?.map((child) => child[props.itemValue]) || []);

View File

@@ -10,6 +10,7 @@
:item-value="itemValue"
:item-children="itemChildren"
:text="choice[itemText]"
:hidden="visibleChildrenValues.includes(choice[itemValue]) === false"
:value="choice[itemValue]"
:children="choice[itemChildren]"
:disabled="disabled"
@@ -19,7 +20,8 @@
</template>
<script lang="ts">
import { computed, ref, defineComponent, PropType } from 'vue';
import { computed, ref, defineComponent, PropType, watch, toRefs } from 'vue';
import { useVisibleChildren } from './use-visible-children';
import VCheckboxTreeCheckbox from './v-checkbox-tree-checkbox.vue';
export default defineComponent({
@@ -74,9 +76,54 @@ export default defineComponent({
},
});
const fakeValue = ref('');
const fakeParentValue = ref('');
const { search, modelValue, showSelectionOnly, itemText, itemValue, itemChildren, choices } = toRefs(props);
const { visibleChildrenValues } = useVisibleChildren(
search,
modelValue,
choices,
showSelectionOnly,
itemText,
itemValue,
itemChildren,
fakeParentValue,
fakeValue
);
const openSelection = ref<(string | number)[]>([]);
return { value, openSelection };
watch(
() => props.search,
(newValue) => {
if (!newValue) return;
const selection = new Set([...openSelection.value, ...searchChoices(newValue, props.choices)]);
openSelection.value = [...selection];
},
{ immediate: true }
);
function searchChoices(text: string, target: Record<string, any>[]) {
const selection: string[] = [];
for (const item of target) {
if (item[props.itemText].toLowerCase().includes(text.toLowerCase())) {
selection.push(item[props.itemValue]);
}
if (item[props.itemChildren]) {
selection.push(...searchChoices(text, item[props.itemChildren]));
}
}
return selection;
}
return { value, openSelection, visibleChildrenValues };
},
});
</script>