add modeling of active items in v-list

This commit is contained in:
Nitwel
2020-10-02 23:59:45 +02:00
parent 508661167e
commit 270990efd2
5 changed files with 117 additions and 29 deletions

View File

@@ -1,5 +1,5 @@
<template>
<div class="v-list-group" v-click-outside="{handler: onClickOutside, events: ['pointerup']}">
<div class="v-list-group">
<v-list-item :active="active" class="activator" :to="to" :exact="exact" @click="onClick" :disabled="disabled">
<slot name="activator" :active="groupActive" />
@@ -15,10 +15,14 @@
</template>
<script lang="ts">
import { defineComponent, nextTick, toRefs, watch } from '@vue/composition-api';
import { defineComponent, nextTick, toRefs, watch, PropType, ref } from '@vue/composition-api';
import { useGroupableParent, useGroupable } from '@/composables/groupable';
export default defineComponent({
model: {
prop: 'activeItems',
event: 'input'
},
props: {
multiple: {
type: Boolean,
@@ -28,6 +32,10 @@ export default defineComponent({
type: String,
default: null,
},
activeItems: {
type: Array as PropType<(number | string)[]>,
default: null
},
active: {
type: Boolean,
default: false,
@@ -51,13 +59,11 @@ export default defineComponent({
value: {
type: [String, Number],
default: undefined,
},
accordion: {
type: Boolean,
default: false
}
},
setup(props, { listeners, emit, root }) {
setup(props, { listeners, emit }) {
const {activeItems, multiple} = toRefs(props)
const { active: groupActive, toggle, activate, deactivate } = useGroupable({
group: props.scope,
value: props.value,
@@ -65,14 +71,21 @@ export default defineComponent({
if (props.disableGroupableParent !== true) {
useGroupableParent(
{},
{
multiple: toRefs(props).multiple,
selection: activeItems,
onSelectionChange: (newSelection) => {
emit('input', newSelection)
}
},
{
multiple
}
);
}
return { groupActive, toggle, onClick, onClickOutside };
return { groupActive, toggle, onClick };
function onClick(event: MouseEvent) {
if (props.to) return null;
@@ -81,10 +94,6 @@ export default defineComponent({
event.stopPropagation();
toggle();
}
function onClickOutside() {
if(props.accordion) deactivate()
}
},
});
</script>

View File

@@ -18,7 +18,15 @@ import { defineComponent, PropType, ref, toRefs } from '@vue/composition-api';
import { useGroupableParent } from '@/composables/groupable';
export default defineComponent({
model: {
prop: 'activeItems',
event: 'input'
},
props: {
activeItems: {
type: Array as PropType<(number | string)[]>,
default: () => []
},
dense: {
type: Boolean,
default: false,
@@ -36,12 +44,18 @@ export default defineComponent({
default: true,
},
},
setup(props) {
setup(props, {emit}) {
const {activeItems, multiple} = toRefs(props)
useGroupableParent(
{},
{
selection: activeItems,
onSelectionChange: (newSelection) => {
emit('input', newSelection)
}
},
{
mandatory: ref(false),
multiple: toRefs(props).multiple,
multiple
}
);

View File

@@ -1,5 +1,5 @@
<template>
<v-list-item v-if="section.children === undefined" :to="section.to" :dense="dense">
<v-list-item v-if="section.children === undefined" :to="section.to" :dense="dense" :value="itemValue">
<v-list-item-icon v-if="section.icon !== undefined"><v-icon :name="section.icon" /></v-list-item-icon>
<v-list-item-content>
<v-list-item-title>{{ section.name }}</v-list-item-title>
@@ -14,7 +14,7 @@
dense
/>
</div>
<v-list-group v-else accordion>
<v-list-group v-else :multiple="false" v-model="rootSelection" :value="itemValue">
<template #activator>
<v-list-item-icon v-if="section.icon !== undefined"><v-icon :name="section.icon" /></v-list-item-icon>
<v-list-item-content>
@@ -22,16 +22,17 @@
</v-list-item-content>
</template>
<navigation-list-item
v-for="(childSection, index) in section.children"
v-for="(child, index) in section.children"
:key="index"
:section="childSection"
:section="child"
v-model="childSelection"
dense
/>
</v-list-group>
</template>
<script lang="ts">
import { defineComponent, PropType } from '@vue/composition-api';
import { defineComponent, PropType, computed } from '@vue/composition-api';
import { Section } from './sections';
export default defineComponent({
@@ -45,7 +46,38 @@ export default defineComponent({
type: Boolean,
default: false,
},
value: {
type: Array as PropType<string[]>,
default: () => []
}
},
setup(props, {emit}) {
const rootSelection = computed({
get() {
if(props.value.length === 0) return []
return [props.value[0]]
},
set(newVal: string[]) {
emit('input', newVal);
}
})
const childSelection = computed({
get() {
if(props.value.length < 2) return []
return props.value.slice(1)
},
set(newVal: string[]) {
emit('input', [props.value[0], ...newVal])
}
})
const itemValue = computed(() => {
return props.section.to.split('/').pop()
})
return {rootSelection, childSelection, itemValue}
}
});
</script>

View File

@@ -1,18 +1,51 @@
<template>
<v-list nav>
<navigation-item v-for="item in sections" :key="item.to" :section="item"></navigation-item>
<v-list nav :multiple="false" v-model="rootSelection">
<navigation-item v-for="item in sections" :key="item.to" :section="item" v-model="childSelection"></navigation-item>
</v-list>
</template>
<script lang="ts">
import { defineComponent } from '@vue/composition-api';
import { computed, defineComponent, PropType, ref, watch } from '@vue/composition-api';
import NavigationItem from './navigation-item.vue';
import sections from './sections';
import sections, {Section} from './sections';
export default defineComponent({
components: { NavigationItem },
setup() {
return { sections };
props: {
section: {
type: Object as PropType<Section>,
default: null,
},
},
setup(props) {
const active = ref<string[]>(props.section.to.replace('/docs/','').split('/'))
watch(props.section, (newSection) => {
if(newSection !== null)
active.value = newSection.to.replace('/docs/','').split('/')
})
const rootSelection = computed({
get() {
if(active.value.length === 0) return []
return [active.value[0]]
},
set(newVal: string[]) {
active.value = newVal
}
})
const childSelection = computed({
get() {
if(active.value.length < 2) return []
return active.value.slice(1)
},
set(newVal: string[]) {
active.value = [active.value[0], ...newVal]
}
})
return { sections, active, childSelection, rootSelection };
},
});
</script>

View File

@@ -9,7 +9,7 @@
</template>
<template #navigation>
<docs-navigation />
<docs-navigation :section="section" />
</template>
<div v-if="notFound" class="not-found">