|
1 | 1 | <script>
|
2 | 2 | import { Input, Select, Button } from "@budibase/bbui"
|
3 | 3 | import { createEventDispatcher } from "svelte"
|
4 |
| -
|
5 |
| - const dispatch = createEventDispatcher() |
| 4 | + import { memo } from "@budibase/frontend-core" |
| 5 | + import { generate } from "shortid" |
6 | 6 |
|
7 | 7 | export let value = {}
|
8 | 8 |
|
9 |
| - $: fieldsArray = value |
10 |
| - ? Object.entries(value).map(([name, type]) => ({ |
11 |
| - name, |
12 |
| - type, |
13 |
| - })) |
14 |
| - : [] |
15 |
| -
|
16 | 9 | const typeOptions = [
|
17 | 10 | {
|
18 | 11 | label: "Text",
|
|
36 | 29 | },
|
37 | 30 | ]
|
38 | 31 |
|
| 32 | + const dispatch = createEventDispatcher() |
| 33 | + const memoValue = memo({ data: {} }) |
| 34 | +
|
| 35 | + $: memoValue.set({ data: value }) |
| 36 | +
|
| 37 | + $: fieldsArray = $memoValue.data |
| 38 | + ? Object.entries($memoValue.data).map(([name, type]) => ({ |
| 39 | + name, |
| 40 | + type, |
| 41 | + id: generate(), |
| 42 | + })) |
| 43 | + : [] |
| 44 | +
|
39 | 45 | function addField() {
|
40 |
| - const newValue = { ...value } |
| 46 | + const newValue = { ...$memoValue.data } |
41 | 47 | newValue[""] = "string"
|
42 |
| - dispatch("change", newValue) |
| 48 | + fieldsArray = [...fieldsArray, { name: "", type: "string", id: generate() }] |
43 | 49 | }
|
44 | 50 |
|
45 |
| - function removeField(name) { |
46 |
| - const newValues = { ...value } |
47 |
| - delete newValues[name] |
48 |
| - dispatch("change", newValues) |
| 51 | + function removeField(idx) { |
| 52 | + const entries = [...fieldsArray] |
| 53 | +
|
| 54 | + // Remove empty field |
| 55 | + if (!entries[idx]?.name) { |
| 56 | + fieldsArray.splice(idx, 1) |
| 57 | + fieldsArray = [...fieldsArray] |
| 58 | + return |
| 59 | + } |
| 60 | +
|
| 61 | + entries.splice(idx, 1) |
| 62 | +
|
| 63 | + const update = entries.reduce((newVals, current) => { |
| 64 | + newVals[current.name.trim()] = current.type |
| 65 | + return newVals |
| 66 | + }, {}) |
| 67 | + dispatch("change", update) |
49 | 68 | }
|
50 | 69 |
|
51 | 70 | const fieldNameChanged = originalName => e => {
|
|
57 | 76 | } else {
|
58 | 77 | entries = entries.filter(f => f.name !== originalName)
|
59 | 78 | }
|
60 |
| - value = entries.reduce((newVals, current) => { |
61 |
| - newVals[current.name.trim()] = current.type |
62 |
| - return newVals |
63 |
| - }, {}) |
64 |
| - dispatch("change", value) |
| 79 | +
|
| 80 | + const update = entries |
| 81 | + .filter(entry => entry.name) |
| 82 | + .reduce((newVals, current) => { |
| 83 | + newVals[current.name.trim()] = current.type |
| 84 | + return newVals |
| 85 | + }, {}) |
| 86 | + if (Object.keys(update).length) { |
| 87 | + dispatch("change", update) |
| 88 | + } |
65 | 89 | }
|
66 | 90 | </script>
|
67 | 91 |
|
68 | 92 | <!-- svelte-ignore a11y-click-events-have-key-events -->
|
69 | 93 | <!-- svelte-ignore a11y-no-static-element-interactions -->
|
70 | 94 | <div class="root">
|
71 | 95 | <div class="spacer" />
|
72 |
| - {#each fieldsArray as field} |
| 96 | + {#each fieldsArray as field, idx (field.id)} |
73 | 97 | <div class="field">
|
74 | 98 | <Input
|
75 | 99 | value={field.name}
|
|
88 | 112 | />
|
89 | 113 | <i
|
90 | 114 | class="remove-field ri-delete-bin-line"
|
91 |
| - on:click={() => removeField(field.name)} |
| 115 | + on:click={() => { |
| 116 | + removeField(idx) |
| 117 | + }} |
92 | 118 | />
|
93 | 119 | </div>
|
94 | 120 | {/each}
|
|
115 | 141 | align-items: center;
|
116 | 142 | gap: var(--spacing-m);
|
117 | 143 | }
|
| 144 | +
|
| 145 | + .remove-field { |
| 146 | + cursor: pointer; |
| 147 | + } |
| 148 | +
|
| 149 | + .remove-field:hover { |
| 150 | + color: var(--spectrum-global-color-gray-900); |
| 151 | + } |
118 | 152 | </style>
|
0 commit comments