Skip to content

Commit dca26f4

Browse files
authored
Merge pull request #89 from devforth/input-prefix-and-suffix
fix: add input prefix and suffix support for columns in forms
2 parents e8dbc00 + 41eeb89 commit dca26f4

File tree

6 files changed

+79
-21
lines changed

6 files changed

+79
-21
lines changed

adminforth/documentation/docs/tutorial/001-gettingStarted.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ export default {
224224
},
225225
{
226226
name: 'price',
227+
inputSuffix: 'USD', // you can add a suffix to an input field that will be displayed when creating or editing records
227228
allowMinMaxQuery: true, // use better experience for filtering e.g. date range, set it only if you have index on this column or if you sure there will be low number of rows
228229
editingNote: 'Price is in USD', // you can put a note near field on editing or creating page
229230
},

adminforth/documentation/docs/tutorial/03-Customization/13-standardPagesTuning.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,28 @@ export default {
370370

371371
> `validation` checks are enforced both on frontend and backend.
372372
373+
### Input prefix and suffix
374+
375+
You can add prefix or suffix to inputs by adding `inputPrefix` or `inputSuffix` fields to a column.
376+
377+
```typescript title="./resources/users.ts"
378+
export default {
379+
name: 'users',
380+
columns: [
381+
...
382+
{
383+
name: "price",
384+
inputSuffix: "USD",
385+
allowMinMaxQuery: true,
386+
},
387+
],
388+
},
389+
...
390+
],
391+
```
392+
393+
These fields can only be used with following `AdminForthDataTypes`: `DECIMAL`, `FLOAT`, `INTEGER`, `STRING` and `JSON` (only if `JSON` column is an array with appropriate `itemType`).
394+
373395
### Editing note
374396

375397
You can add `editingNote` to a column to show a note below the input field.

adminforth/modules/configValidator.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,26 @@ export default class ConfigValidator implements IConfigValidator {
461461
}
462462
}
463463

464+
if (inCol.inputPrefix || inCol.inputSuffix) {
465+
if (![AdminForthDataTypes.DECIMAL, AdminForthDataTypes.FLOAT, AdminForthDataTypes.INTEGER, AdminForthDataTypes.STRING, undefined].includes(col.type)) {
466+
if (inCol.type === AdminForthDataTypes.JSON) {
467+
if (inCol.isArray && inCol.isArray.enabled && ![AdminForthDataTypes.DECIMAL, AdminForthDataTypes.FLOAT, AdminForthDataTypes.INTEGER, AdminForthDataTypes.STRING].includes(inCol.isArray.itemType)) {
468+
errors.push(`Resource "${res.resourceId}" column "${col.name}" has input${inCol.inputPrefix ? 'Prefix': 'Suffix'} but it is not supported for array columns item type: ${inCol.isArray.itemType}`);
469+
} else if (!inCol.isArray || !inCol.isArray.enabled) {
470+
errors.push(`Resource "${res.resourceId}" column "${col.name}" has input${inCol.inputPrefix ? 'Prefix' : 'Suffix'} but it is not supported for this column type: ${col.type}`);
471+
}
472+
} else {
473+
errors.push(`Resource "${res.resourceId}" column "${col.name}" has input${inCol.inputPrefix ? 'Prefix' : 'Suffix'} but it is not supported for this column type: ${col.type}`);
474+
}
475+
}
476+
if (inCol.enum) {
477+
errors.push(`Resource "${res.resourceId}" column "${col.name}" has input${inCol.inputPrefix ? 'Prefix' : 'Suffix'} but it is not supported for enum columns`);
478+
}
479+
if (inCol.foreignResource) {
480+
errors.push(`Resource "${res.resourceId}" column "${col.name}" has input${inCol.inputPrefix ? 'Prefix' : 'Suffix'} but it is not supported for foreignResource columns`);
481+
}
482+
}
483+
464484
// check is all custom components files exists
465485
if (col.components) {
466486
for (const [key, comp] of Object.entries(col.components as Record<string, AdminForthComponentDeclarationFull>)) {

adminforth/spa/src/afcl/Input.vue

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
<div class="flex z-0">
44
<span
5-
v-if="$slots.prefix"
6-
class="inline-flex items-center px-3 text-sm text-gray-900 bg-gray-200 border border-s-0 border-gray-300 rounded-e-md dark:bg-gray-600 dark:text-gray-400 dark:border-gray-600">
7-
<slot name="prefix"></slot>
5+
v-if="$slots.prefix || prefix"
6+
class="inline-flex items-center px-3 text-sm text-gray-900 bg-gray-200 border border-s-0 border-gray-300 rounded-s-md dark:bg-gray-600 dark:text-gray-400 dark:border-gray-600">
7+
<slot name="prefix">{{ prefix }}</slot>
88
</span>
99

1010
<!-- translate needed for bumping ring above prefix without z-index -->
@@ -16,14 +16,14 @@
1616
aria-describedby="helper-text-explanation"
1717
class="inline-flex bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-0 focus:ring-lightPrimary focus:border-lightPrimary dark:focus:ring-darkPrimary dark:focus:border-darkPrimary
1818
blue-500 focus:border-blue-500 block w-20 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white translate-y-0"
19-
:class="{'rounded-l-md': !$slots.prefix, 'rounded-r-md': !$slots.suffix, 'w-full': fullWidth}"
19+
:class="{'rounded-l-md': !$slots.prefix && !prefix, 'rounded-r-md': !$slots.suffix && !suffix, 'w-full': fullWidth}"
2020
>
2121

2222

2323
<span
24-
v-if="$slots.suffix"
24+
v-if="$slots.suffix || suffix"
2525
class="inline-flex items-center px-3 text-sm text-gray-900 bg-gray-200 border border-s-0 border-gray-300 rounded-e-md dark:bg-gray-600 dark:text-gray-400 dark:border-gray-600 ">
26-
<slot name="suffix"></slot>
26+
<slot name="suffix">{{ suffix }}</slot>
2727
</span>
2828

2929
</div>
@@ -35,6 +35,8 @@ const props = defineProps({
3535
type: String,
3636
fullWidth: Boolean,
3737
modelValue: String,
38+
suffix: String,
39+
prefix: String,
3840
})
3941
4042

adminforth/spa/src/components/ColumnValueInput.vue

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,19 @@
3939
:readonly="column.editReadonly && source === 'edit'"
4040
@update:modelValue="$emit('update:modelValue', $event)"
4141
/>
42-
<input
42+
<Input
4343
v-else-if="['integer'].includes(type || column.type)"
4444
ref="input"
45-
type="number"
45+
type="number"
4646
step="1"
47-
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg block w-40 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white focus:ring-lightPrimary focus:border-lightPrimary dark:focus:ring-darkPrimary dark:focus:border-darkPrimary"
47+
class="w-40"
4848
placeholder="0"
49+
:prefix="column.inputPrefix"
50+
:suffix="column.inputSuffix"
4951
:readonly="column.editReadonly && source === 'edit'"
50-
:value="value"
51-
@input="$emit('update:modelValue', $event.target.value)"
52-
>
52+
:modelValue="value"
53+
@update:modelValue="$emit('update:modelValue', $event)"
54+
/>
5355
<CustomDatePicker
5456
v-else-if="['datetime'].includes(type || column.type)"
5557
ref="input"
@@ -59,15 +61,17 @@
5961
@update:valueStart="$emit('update:modelValue', $event)"
6062
:readonly="column.editReadonly && source === 'edit'"
6163
/>
62-
<input
64+
<Input
6365
v-else-if="['decimal', 'float'].includes(type || column.type)"
6466
ref="input"
6567
type="number"
6668
step="0.1"
67-
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg block w-40 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white focus:ring-lightPrimary focus:border-lightPrimary dark:focus:ring-darkPrimary dark:focus:border-darkPrimary"
69+
class="w-40"
6870
placeholder="0.0"
69-
:value="value"
70-
@input="$emit('update:modelValue', $event.target.value)"
71+
:prefix="column.inputPrefix"
72+
:suffix="column.inputSuffix"
73+
:modelValue="value"
74+
@update:modelValue="$emit('update:modelValue', $event)"
7175
:readonly="column.editReadonly && source === 'edit'"
7276
/>
7377
<textarea
@@ -87,19 +91,21 @@
8791
:value="value"
8892
@input="$emit('update:modelValue', $event.target.value)"
8993
/>
90-
<input
94+
<Input
9195
v-else
9296
ref="input"
9397
:type="!column.masked || unmasked[column.name] ? 'text' : 'password'"
94-
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white focus:ring-lightPrimary focus:border-lightPrimary dark:focus:ring-darkPrimary dark:focus:border-darkPrimary"
98+
class="w-full"
9599
:placeholder="$t('Text')"
96-
:value="value"
97-
@input="$emit('update:modelValue', $event.target.value)"
100+
:prefix="column.inputPrefix"
101+
:suffix="column.inputSuffix"
102+
:modelValue="value"
103+
@update:modelValue="$emit('update:modelValue', $event)"
98104
autocomplete="false"
99105
data-lpignore="true"
100106
readonly
101107
@focus="onFocusHandler($event, column, source)"
102-
>
108+
/>
103109

104110
<button
105111
v-if="deletable"
@@ -125,6 +131,7 @@
125131
import { IconEyeSlashSolid, IconEyeSolid, IconTrashBinSolid } from '@iconify-prerendered/vue-flowbite';
126132
import CustomDatePicker from "@/components/CustomDatePicker.vue";
127133
import Select from '@/afcl/Select.vue';
134+
import Input from '@/afcl/Input.vue';
128135
import { ref } from 'vue';
129136
import { getCustomComponent } from '@/utils';
130137
import { useI18n } from 'vue-i18n';

adminforth/types/Common.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,12 @@ export interface AdminForthResourceColumnInputCommon {
615615
*/
616616
required?: boolean | { create?: boolean, edit?: boolean },
617617

618+
/**
619+
* Prefix and suffix for input field on create and edit pages.
620+
*/
621+
inputPrefix?: string,
622+
inputSuffix?: string,
623+
618624
/**
619625
* Whether AdminForth will show editing note near the field in edit/create form.
620626
*/

0 commit comments

Comments
 (0)