Google maps style text input

Hi, I'm trying to make a TextInput in a form make a call to a Nominatim (OSM) api that I've setup myself. I need to type an address into the input and the possible results should load below in a Select input. Ideally, they'd be together in the same input. I'm not entirely sure how I could do this with filament. Any ideas?
7 Replies
fenerli
fenerli6d ago
You'll need to create a custom form component with a TextInput for the address and a SelectInput for the results. Here’s a simplified approach: First, set up your form in the appropriate Filament resource: use Filament\Forms; use Filament\Forms\Components\TextInput; use Filament\Forms\Components\Select; public function form(Form $form): Form { return $form ->schema([ TextInput::make('address') ->label('Address') ->reactive() ->afterStateUpdated(fn ($state, callable $get) => $this->fetchAddresses($state)),
Select::make('address_results') ->label('Possible Addresses') ->options(fn ($get) => $get('address_options') ?? []) ->reactive() ->hidden(fn ($get) => !$get('address_options')), // Show only if there are options ]); } You'll need to implement the fetchAddresses method to make an API call to your Nominatim server: protected function fetchAddresses($address) { if (empty($address)) { return; } $response = Http::get('YOUR_NOMINATIM_API_URL', [ 'q' => $address, 'format' => 'json', ]); if ($response->successful()) { $results = $response->json();
// Create options for the Select component $options = []; foreach ($results as $result) { $options[$result['place_id']] = $result['display_name']; } // Update the state with the options $this->fill(['address_options' => $options]); } } You may want to handle the selection in such a way that when a user selects an address from the dropdown, it populates the TextInput. You can achieve this with a little JavaScript. <script> document.addEventListener('DOMContentLoaded', function() { const addressInput = document.querySelector('input[name="address"]'); const addressSelect = document.querySelector('select[name="address_results"]'); if (addressSelect) { addressSelect.addEventListener('change', function() { addressInput.value = this.options[this.selectedIndex].text; }); } }); </script>
Kanalaetxebarria
Hey thanks for your reply! I've found this: https://filamentphp.com/docs/3.x/forms/fields/select#returning-custom-search-results - I feel like there might be something here. I'll go down this route for a bit and see if it works, otherwise I'll give your solution a shot!
Kanalaetxebarria
👆 worked like a charm!
fenerli
fenerli6d ago
okay. if you want web developer, I can make your project perfectly from start to end.
raheel3031
raheel30316d ago
what did you do?
Carl-bot
Carl-bot6d ago
osedyo has been warned, this is their 2nd warning.
Kanalaetxebarria
I'm a fullstack dev 😂
Forms\Components\Select::make('search_address')
->live(onBlur: true)
->searchable()
->getSearchResultsUsing(function (string $search) {
$response = Http::get('https://my-api/search', [
'addressdetails' => 1,
'q' => $search,
'format' => 'json',
]);
...

->getOptionLabelUsing(function ($value) { $storedData = session("address_data_{$value}");
return $storedData ? $storedData['display_name'] : null;
})
->afterStateUpdated(function (Get $get, Set $set, $state) { $storedData = session("address_data_{$state}");
Forms\Components\Select::make('search_address')
->live(onBlur: true)
->searchable()
->getSearchResultsUsing(function (string $search) {
$response = Http::get('https://my-api/search', [
'addressdetails' => 1,
'q' => $search,
'format' => 'json',
]);
...

->getOptionLabelUsing(function ($value) { $storedData = session("address_data_{$value}");
return $storedData ? $storedData['display_name'] : null;
})
->afterStateUpdated(function (Get $get, Set $set, $state) { $storedData = session("address_data_{$state}");
Want results from more Discord servers?
Add your server