Skip to content

Commit d9d5f33

Browse files
fix the formList component
1 parent 6e5eeb7 commit d9d5f33

File tree

5 files changed

+139
-89
lines changed

5 files changed

+139
-89
lines changed

src/App.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
</template>
66

77
<script setup lang="ts">
8-
import CP1 from "./views/FormGeneratorArrayTest.vue";
8+
import CP1 from "./views/FormListTest.vue";
99
</script>

src/components/FormList.vue

Lines changed: 71 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,72 @@
1+
<script lang="ts" setup>
2+
import FormLabel from "./FormLabel.vue";
3+
import FormHelptext from "./FormHelptext.vue";
4+
import { computed, toRefs } from "vue";
5+
import {
6+
XMarkIcon,
7+
PlusIcon,
8+
ArrowSmallUpIcon,
9+
} from "@heroicons/vue/24/outline";
10+
11+
const props = defineProps<{
12+
label: string;
13+
name: string;
14+
modelValue: string[];
15+
required?: boolean;
16+
helptext?: string;
17+
}>();
18+
const { modelValue } = toRefs(props);
19+
20+
const emit = defineEmits(["update:modelValue"]);
21+
22+
type Value = Record<string, string>;
23+
24+
const value = computed<Value>({
25+
get: () => {
26+
const ret = modelValue.value.reduce(
27+
(acc, curr, index) => ({ ...acc, [index + 1]: curr }),
28+
{},
29+
);
30+
return ret;
31+
},
32+
set: (val: Value) => {
33+
emit("update:modelValue", Object.values(val));
34+
},
35+
});
36+
37+
function add() {
38+
const key =
39+
Math.max(...Object.keys(value.value).map((x) => parseInt(x)), 0) + 1;
40+
const newValue = { ...value.value, [key]: "" };
41+
value.value = newValue;
42+
}
43+
44+
function remove(key: string) {
45+
const newValue = { ...value.value };
46+
delete newValue[key];
47+
value.value = newValue;
48+
}
49+
50+
function up(k: string) {
51+
const key = parseInt(k);
52+
const newValue = { ...value.value };
53+
if (key > 0) {
54+
newValue[key] = value.value[key - 1];
55+
newValue[key - 1] = value.value[key];
56+
}
57+
value.value = newValue;
58+
}
59+
60+
function change() {
61+
emit("update:modelValue", Object.values(value.value));
62+
}
63+
</script>
64+
165
<template>
2-
<label :for="name" class="relative block">
3-
<FormLabel :required="required" :label="label" />
66+
<fieldset class="relative block">
67+
<legend>
68+
<FormLabel :required="required" :label="label" />
69+
</legend>
470
<div class="flex items-center mt-2 space-x-2">
571
<div class="flex flex-col items-start w-full space-y-2">
672
<div
@@ -9,7 +75,9 @@
975
class="flex items-center w-full space-x-3"
1076
>
1177
<input
78+
:id="`form-input-${name}-${key}`"
1279
v-model="value[key]"
80+
:name="name"
1381
type="text"
1482
class="flex-grow block w-full px-3 py-2 placeholder-gray-400 border border-gray-300 rounded-md shadow-sm appearance-none focus:outline-none focus:ring-formcolor focus:border-formcolor focus:ring-1 sm:text-sm"
1583
@change="change()"
@@ -39,89 +107,5 @@
39107
</div>
40108
</div>
41109
<FormHelptext :helptext="helptext" />
42-
</label>
110+
</fieldset>
43111
</template>
44-
45-
<script lang="ts">
46-
import FormLabel from "./FormLabel.vue";
47-
import FormHelptext from "./FormHelptext.vue";
48-
import { defineComponent, PropType } from "vue";
49-
import {
50-
XMarkIcon,
51-
PlusIcon,
52-
ArrowSmallUpIcon,
53-
} from "@heroicons/vue/24/outline";
54-
55-
export default defineComponent({
56-
components: {
57-
FormHelptext,
58-
XMarkIcon,
59-
FormLabel,
60-
PlusIcon,
61-
ArrowSmallUpIcon,
62-
},
63-
props: {
64-
label: {
65-
required: true,
66-
type: String,
67-
},
68-
name: {
69-
required: true,
70-
type: String,
71-
},
72-
modelValue: {
73-
required: false,
74-
default: () => [],
75-
type: Array as PropType<string[]>,
76-
},
77-
required: {
78-
required: false,
79-
default: false,
80-
type: Boolean,
81-
},
82-
helptext: {
83-
required: false,
84-
default: "",
85-
type: String,
86-
},
87-
},
88-
emits: ["update:modelValue"],
89-
data() {
90-
return {
91-
value: {} as { [key: number]: string },
92-
};
93-
},
94-
watch: {
95-
modelValue(newValue) {
96-
this.value = {};
97-
newValue.forEach((element: string, index: number) => {
98-
this.value[index] = element;
99-
});
100-
},
101-
},
102-
methods: {
103-
add() {
104-
const key =
105-
Math.max(...Object.keys(this.value).map((x) => parseInt(x)), 0) + 1;
106-
this.value[key] = "";
107-
this.change();
108-
},
109-
remove(key: string) {
110-
delete this.value[key];
111-
this.change();
112-
},
113-
up(k: string) {
114-
const key = parseInt(k);
115-
if (key > 0) {
116-
const temp = this.value[key];
117-
this.value[key] = this.value[key - 1];
118-
this.value[key - 1] = temp;
119-
}
120-
this.change();
121-
},
122-
change() {
123-
this.$emit("update:modelValue", Object.values(this.value));
124-
},
125-
},
126-
});
127-
</script>

src/tests/FormList.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { mount } from "@vue/test-utils";
2+
import FormListVue from "src/components/FormList.vue";
3+
4+
describe("form datalist", () => {
5+
it("shows label and helptext", async () => {
6+
const formlist = mount(FormListVue, {
7+
props: {
8+
label: "Test 01",
9+
helptext: "Help text 23",
10+
name: "test",
11+
modelValue: ["initialText"],
12+
},
13+
});
14+
15+
expect(formlist.text()).toContain("Test 01");
16+
expect(formlist.text()).toContain("Help text 23");
17+
});
18+
it("shows the model value", async () => {
19+
const formlist = mount(FormListVue, {
20+
props: {
21+
label: "Test 01",
22+
helptext: "Help text 23",
23+
name: "test",
24+
modelValue: ["Custom Value 1", "Another Value 2"],
25+
},
26+
});
27+
28+
const inputValues = await formlist.findAll("input");
29+
expect(inputValues[0].element.value).toBe("Custom Value 1");
30+
expect(inputValues[1].element.value).toBe("Another Value 2");
31+
});
32+
});

src/types/form.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type InputField = BaseField & {
2929
| "toggle" // form checkbox
3030
| "file" // form file
3131
| "files" // form files
32+
| "list" // form list
3233
| "custom"
3334
// form input
3435
| "button"
@@ -56,7 +57,6 @@ type InputField = BaseField & {
5657
type OptionsField = BaseField & {
5758
type:
5859
| "multiple" // form multiple
59-
| "list" // form list
6060
| "select" // form select
6161
| "combobox" // form combobox
6262
| "searchselect" // form searchselect

src/views/FormListTest.vue

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<script setup lang="ts">
2+
import ButtonNormal from "../components/ButtonNormal.vue";
3+
import { FormField } from "../types/form";
4+
import { computed, ref } from "vue";
5+
import ModalUpdate from "../components/ModalUpdate.vue";
6+
7+
const commandModalOpen = ref(false);
8+
const request = () => Promise.resolve();
9+
const fields = computed<FormField[]>(() => [
10+
{
11+
label: "Properties",
12+
name: "property_names",
13+
type: "list",
14+
required: true,
15+
},
16+
]);
17+
18+
const propertyNames = ref(["name", "description", "price"]);
19+
</script>
20+
21+
<template>
22+
<ButtonNormal kind="action" @click="commandModalOpen = true">
23+
Reorder Properties
24+
</ButtonNormal>
25+
<ModalUpdate
26+
v-model="commandModalOpen"
27+
title="Reorder Properties"
28+
:fields="fields"
29+
:request="request"
30+
:data="{
31+
property_names: propertyNames,
32+
}"
33+
/>
34+
</template>

0 commit comments

Comments
 (0)