Skip to content

Commit 3ee7650

Browse files
author
antoine
committed
more autocomplete front
1 parent 071e715 commit 3ee7650

File tree

6 files changed

+54
-52
lines changed

6 files changed

+54
-52
lines changed

demo/app/Sharp/TestForm/TestForm.php

Lines changed: 19 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -37,20 +37,19 @@ public function buildFormFields(FieldsContainer $formFields): void
3737
)
3838
->addField(
3939
SharpFormAutocompleteLocalField::make('autocomplete_local')
40-
->setLocalized()
4140
->setLabel('Autocomplete local')
4241
->setLocalSearchKeys(['label'])
4342
->setListItemTemplate('{{ $label }}')
4443
->setResultItemTemplate('{{ $label }} ({{ $id }})')
45-
->setLocalValues($this->options(true)),
44+
->setLocalValues($this->options()),
4645
)
4746
->addField(
4847
SharpFormAutocompleteRemoteField::make('autocomplete_remote')
4948
->setLabel('Autocomplete remote')
5049
->setRemoteSearchAttribute('query')
51-
->setListItemInlineTemplate('{{name}}')
52-
->setResultItemInlineTemplate('{{name}} ({{num}})')
53-
->setRemoteEndpoint(url('/passengers')),
50+
->setListItemTemplate('{{ $name }}')
51+
->setResultItemTemplate('{{ $name }} ({{ $num }})')
52+
->setRemoteEndpoint('/api/admin/users'),
5453
)
5554
->addField(
5655
SharpFormAutocompleteListField::make('autocomplete_list')
@@ -209,28 +208,28 @@ public function buildFormFields(FieldsContainer $formFields): void
209208
->setStep(.1),
210209
)
211210
->addField(
212-
SharpFormSelectField::make('select_dropdown', $this->options(true))
211+
SharpFormSelectField::make('select_dropdown', $this->options())
213212
->setLocalized()
214213
->setLabel('Select dropdown')
215214
->setMultiple()
216215
->setDisplayAsDropdown(),
217216
)
218217
->addField(
219-
SharpFormSelectField::make('select_list', $this->options(true))
218+
SharpFormSelectField::make('select_list', $this->options())
220219
->setLocalized()
221220
->setLabel('Select list')
222221
->setDisplayAsList(),
223222
)
224223
->addField(
225-
SharpFormSelectField::make('select_list_multiple', $this->options(true))
224+
SharpFormSelectField::make('select_list_multiple', $this->options())
226225
->setLocalized()
227226
->setLabel('Select list multiple')
228227
->setMultiple()
229228
->setDisplayAsList()
230229
->setMaxSelected(2),
231230
)
232231
->addField(
233-
SharpFormTagsField::make('tags', $this->options(true))
232+
SharpFormTagsField::make('tags', $this->options())
234233
->setLocalized()
235234
->setLabel('Tags')
236235
->setCreatable(true)
@@ -375,33 +374,19 @@ public function getDataLocalizations(): array
375374
return ['fr', 'en'];
376375
}
377376

378-
protected function options(bool $localized = false): array
377+
protected function options(): array
379378
{
380-
if (! $localized) {
381-
return [
382-
'1' => 'Option one',
383-
'2' => 'Option two',
384-
'3' => 'Option three',
385-
];
386-
}
387-
388379
return [
389-
'1' => ['en' => 'Option one', 'fr' => 'Option un'],
390-
'2' => ['en' => 'Option two', 'fr' => 'Option deux'],
391-
'3' => ['en' => 'Option three', 'fr' => 'Option trois'],
392-
'4' => ['en' => 'Option four', 'fr' => 'Option quatre'],
393-
'5' => ['en' => 'Option five', 'fr' => 'Option cinq'],
394-
'6' => ['en' => 'Option six', 'fr' => 'Option six'],
395-
'7' => ['en' => 'Option seven', 'fr' => 'Option sept'],
396-
'8' => ['en' => 'Option eight', 'fr' => 'Option huit'],
397-
'9' => ['en' => 'Option nine', 'fr' => 'Option neuf'],
398-
'10' => ['en' => 'Option ten', 'fr' => 'Option dix'],
399-
'11' => ['en' => 'Option eleven', 'fr' => 'Option onze'],
400-
'12' => ['en' => 'Option twelve', 'fr' => 'Option douze'],
401-
'13' => ['en' => 'Option thirteen', 'fr' => 'Option treize'],
402-
'14' => ['en' => 'Option fourteen', 'fr' => 'Option quatorze'],
403-
'15' => ['en' => 'Option fifteen', 'fr' => 'Option quinze'],
404-
'16' => ['en' => 'Option sixteen', 'fr' => 'Option seize'],
380+
'1' => 'Option one',
381+
'2' => 'Option two',
382+
'3' => 'Option three',
383+
'4' => 'Option four',
384+
'5' => 'Option five',
385+
'6' => 'Option six',
386+
'7' => 'Option seven',
387+
'8' => 'Option eight',
388+
'9' => 'Option nine',
389+
'10' => 'Option ten',
405390
];
406391
}
407392
}

resources/js/form/components/fields/Autocomplete.vue

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import FormFieldLayout from "@/form/components/FormFieldLayout.vue";
33
import { FormFieldEmits, FormFieldProps } from "@/form/types";
44
import {
5+
FormAutocompleteItemData,
56
FormAutocompleteLocalFieldData,
67
FormAutocompleteRemoteFieldData,
78
} from "@/types";
@@ -46,24 +47,32 @@
4647
signal: abort.signal,
4748
})
4849
.then(response => response.data.data);
49-
}, 300);
50+
}, 200);
5051
5152
function search(query: string) {
5253
if(props.field.mode === 'remote') {
5354
if(query.length >= props.field.searchMinChars) {
5455
remoteSearch(query);
5556
}
5657
} else {
57-
if(query.length > 0) {
58-
results.value = fuzzySearch(props.field.localValues, query, { searchKeys: props.field.searchKeys });
59-
}
58+
results.value = !query.length ? props.field.localValues : fuzzySearch(props.field.localValues, query, { searchKeys: props.field.searchKeys });
6059
}
6160
}
6261
62+
function onOpen() {
63+
if((props.field.mode === 'remote' && props.field.searchMinChars === 0 || props.field.mode === 'local') && !searchTerm.value) {
64+
search('');
65+
}
66+
}
67+
68+
function onSelect(result: FormAutocompleteItemData) {
69+
emit('input', result);
70+
open.value = false;
71+
}
72+
6373
if(props.field.mode === 'local' && props.value) {
6474
const localValue = props.field.localValues
6575
.find(v => props.value[props.field.itemIdAttribute] == v[props.field.itemIdAttribute]);
66-
console.log(localValue);
6776
if(localValue) {
6877
emit('input', localValue, { force: true });
6978
}
@@ -72,30 +81,33 @@
7281

7382
<template>
7483
<FormFieldLayout :field="props.field">
75-
<Popover v-model:open="open">
84+
<Popover v-model:open="open" @update:open="$event ? onOpen() : null">
7685
<template v-if="props.value">
77-
<div class="relative border border-input flex items-center rounded-md min-h-10 text-sm px-3 py-2">
78-
<div class="flex-1" v-html="props.value._htmlResult ?? props.value._html ?? props.value[props.field.itemIdAttribute]"></div>
79-
<Button class="absolute right-0 top-1/2 -translate-y-1/2" variant="ghost" size="icon" @click="$emit('input', null)">
80-
<X class="size-4" />
81-
</Button>
82-
</div>
86+
<PopoverTrigger as-child>
87+
<div class="relative border border-input flex items-center rounded-md min-h-10 text-sm px-3 py-2">
88+
<div class="flex-1" @click.stop v-html="props.value._htmlResult ?? props.value._html ?? props.value[props.field.itemIdAttribute]"></div>
89+
<Button class="absolute right-0 h-[2.375rem] top-1/2 -translate-y-1/2" variant="ghost" size="icon" @click="$emit('input', null)">
90+
<X class="size-4 opacity-50" />
91+
</Button>
92+
</div>
93+
</PopoverTrigger>
8394
</template>
8495
<template v-else>
8596
<PopoverTrigger as-child>
86-
<Button class="w-full justify-between" variant="outline">
87-
{{ props.field.placeholder ?? __('sharp::form.multiselect.placeholder') }}
88-
<ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
97+
<Button class="w-full justify-between text-muted-foreground px-3" variant="outline">
98+
{{ props.field.placeholder ?? __('sharp::form.autocomplete.placeholder') }}
99+
<ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50 text-foreground" />
89100
</Button>
90101
</PopoverTrigger>
91102
</template>
103+
92104
<PopoverContent :class="cn('p-0 w-[--radix-popover-trigger-width] min-w-[200px]')" align="start">
93105
<Command
94106
v-model:searchTerm="searchTerm"
95-
@update:modelValue="$emit('input', $event as any)"
107+
@update:modelValue="onSelect($event as any)"
96108
@update:searchTerm="search($event)"
97109
>
98-
<CommandInput :placeholder="__('sharp::form.multiselect.placeholder')" />
110+
<CommandInput />
99111
<CommandList>
100112
<CommandEmpty>{{ __('sharp::form.autocomplete.no_results_text') }}</CommandEmpty>
101113
<CommandGroup>

resources/lang/en/form.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
'select.validation.max_selected' => 'Too many items selected (:max_selected max.)',
4646

4747
'autocomplete.no_results_text' => 'No result found',
48+
'autocomplete.placeholder' => 'Search...',
4849

4950
'date.validation_error.format' => 'Invalid date format',
5051

resources/lang/fr/form.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
'select.validation.max_selected' => 'Trop d’éléments sélectionnés (:max_selected max.)',
4646

4747
'autocomplete.no_results_text' => 'Pas de résultats',
48+
'autocomplete.placeholder' => 'Rechercher...',
4849

4950
'date.validation_error.format' => 'Format de date invalide',
5051

src/Form/Fields/Utils/SharpFormAutocompleteCommonField.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public function itemWithRenderedTemplates(array $item): array
2525
$resultItem = $this->resultItemTemplate
2626
? ['_htmlResult' => $this->renderResultItem($item)]
2727
: [];
28-
28+
2929
return [
3030
...$item,
3131
'_html' => $this->listItemTemplate

src/Http/Controllers/Api/ApiFormAutocompleteController.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ public function index(string $entityKey, string $autocompleteFieldKey)
6767
);
6868

6969
$data = Arr::get(json_decode($response->getContent(), true), $field->dataWrapper() ?: null);
70+
if($response->getStatusCode() >= 400) {
71+
abort($response);
72+
}
7073
// }
7174
}
7275

0 commit comments

Comments
 (0)