/
KtFormControllerList.vue
154 lines (145 loc) · 4.08 KB
/
KtFormControllerList.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<template>
<div>
<slot
v-bind="slotFunctions"
name="header"
:values="cloneDeep(valuesList)"
/>
<FormControllerListItem
v-for="(values, index) in valuesList"
:key="index"
:context="context"
:formKey="formKey"
:index="index"
:values="values"
@setValue="setValue({ ...$event, index })"
>
<slot
:addAfter="(newRow) => addAfter(index, newRow)"
:addBefore="(newRow) => addBefore(index, newRow)"
:deleteSelf="() => deleteSelf(index)"
:index="index"
name="default"
:setValues="(newValue) => setValuesIndex(index, newValue)"
:values="cloneDeep(values)"
/>
</FormControllerListItem>
<slot
v-bind="slotFunctions"
name="footer"
:values="cloneDeep(valuesList)"
/>
</div>
</template>
<script lang="ts">
import { defineComponent, inject, computed } from '@vue/composition-api'
import cloneDeep from 'lodash/cloneDeep'
import { KT_FORM_CONTEXT } from '../kotti-form/constants'
import { KottiForm } from '../kotti-form/types'
import FormControllerListItem from './components/FormControllerListItem.vue'
import { KottiFormControllerList, KottiFormControllerListItem } from './types'
type Entry = KottiFormControllerListItem.Props['values']
export default defineComponent({
name: 'KtFormControllerList',
components: { FormControllerListItem },
props: {
formKey: { required: true, type: String },
},
setup(props: KottiFormControllerList.Props) {
const context = inject<KottiForm.Context | null>(KT_FORM_CONTEXT, null)
if (context === null)
throw new Error('KtFormControllerList: Could Not Find KtFormContext')
const valuesList = computed<Entry[]>(() => {
const result = context.values.value[props.formKey]
if (!Array.isArray(result))
throw new Error(
`KtFormControllerList: Unexpected Data Type ${typeof result}. Expected Array`,
)
return result
})
return {
/**
* Adds a new valuesList entry after the given index
*/
addAfter: (index: number, newRow: Entry) =>
context.setValue(props.formKey, [
...valuesList.value.slice(0, index + 1),
newRow,
...valuesList.value.slice(index + 1, valuesList.value.length),
]),
/**
* Adds a new valuesList entry before the given index
*/
addBefore: (index: number, newRow: Entry) =>
context.setValue(props.formKey, [
...valuesList.value.slice(0, index),
newRow,
...valuesList.value.slice(index, valuesList.value.length),
]),
/**
* Makes sure that consumers cannot accidentally modify the internal state
*/
cloneDeep,
context,
/**
* Deletes the given index from the valuesList
*/
deleteSelf: (index: number) =>
context.setValue(
props.formKey,
valuesList.value.filter((_, i) => (i === index ? false : true)),
),
/**
* Updates a single formKey in a valuesList entry
*/
setValue: ({
formKey,
index,
newValue,
}: {
formKey: string
index: number
newValue: unknown
}) =>
context.setValue(
props.formKey,
valuesList.value.map((oldValue, i) =>
i === index ? { ...oldValue, [formKey]: newValue } : oldValue,
),
),
/**
* Replaces an entire valuesListEntry with new data
*/
setValuesIndex: (index: number, newValue: Entry) =>
context.setValue(
props.formKey,
valuesList.value.map((oldValue, i) =>
i === index ? newValue : oldValue,
),
),
/**
* Functions that are exposed to the footer and header slots
* these should manipulate the entire array, instead of individual items
*/
slotFunctions: {
/**
* Adds a new valuesList entry to the end of the entire list
*/
addAfter: (newRow: Entry) =>
context.setValue(props.formKey, [...valuesList.value, newRow]),
/**
* Adds a new valuesList entry to the beginning of the entire list
*/
addBefore: (newRow: Entry) =>
context.setValue(props.formKey, [newRow, ...valuesList.value]),
/**
* Replaces the entire valuesList with a new one
*/
setValues: (newValuesList: Entry[]) =>
context.setValue(props.formKey, newValuesList),
},
valuesList,
}
},
})
</script>