refresh select after suffixAction completed

I need to refresh my select options after the suffix action is completed. How would I accomplish this? Maybe using afterStateUpdated()?
Select::make('quickbooks_vendor_ref_id')
->required()
->label('Vendor')
->options($this->getVendors())
->live()
->preload()
->searchable()
->loadingMessage('Loading vendors...')
// ->afterStateUpdated() <--maybe use this to get the drop down to rerender after force refresh.
->suffixAction(
Action::make('refreshVendors')
->label('Refresh Vendors')
->icon('heroicon-o-arrow-path')
->action(fn () => $this->getVendors(true))
),
Select::make('quickbooks_vendor_ref_id')
->required()
->label('Vendor')
->options($this->getVendors())
->live()
->preload()
->searchable()
->loadingMessage('Loading vendors...')
// ->afterStateUpdated() <--maybe use this to get the drop down to rerender after force refresh.
->suffixAction(
Action::make('refreshVendors')
->label('Refresh Vendors')
->icon('heroicon-o-arrow-path')
->action(fn () => $this->getVendors(true))
),
Solution:
use ->options(fn () => $this->vendors)
Jump to solution
10 Replies
Čamap
Čamap2mo ago
Have you found any solution to this?
MohamedSabil83
MohamedSabil832mo ago
You can do something similar to the following, but notice that it works when you don't use ->searchable():
->suffixAction(Forms\Components\Actions\Action::make('test')
->label('Test')
->icon('heroicon-o-home')
->action(function ($component) {
$component->options(['A' => 'B']);
})
)
->suffixAction(Forms\Components\Actions\Action::make('test')
->label('Test')
->icon('heroicon-o-home')
->action(function ($component) {
$component->options(['A' => 'B']);
})
)
awcodes
awcodes2mo ago
Try $component->callAfterStateUpdated() in the action callback. That should work even with searchable. Not sure exactly what you are trying to accomplish though.
LeandroFerreira
LeandroFerreira2mo ago
Are you using a resource or custom LW component?
public ?array $data = [];

public $vendors = [];

public function mount(): void
{
$this->vendors = [
'1' => 'Vendor 1',
'2' => 'Vendor 2',
'3' => 'Vendor 3',
];

$this->form->fill();
}

public function updateVendors(array $vendors)
{
$this->vendors = $vendors;
}

public function form(Form $form): Form
{
return $form
->schema([
Select::make('quickbooks_vendor_ref_id')
->label('Vendor')
->options(fn () => $this->vendors)
->preload()
->searchable()
->suffixAction(
Action::make('refreshVendors')
->label('Refresh Vendors')
->icon('heroicon-o-arrow-path')
->action(function (Select $component) {
$component->state(null);

$newVendors = [
'4' => 'Vendor 4',
'5' => 'Vendor 5',
'6' => 'Vendor 6',
];
$this->updateVendors($newVendors);
})
),
])
->statePath('data');
}
public ?array $data = [];

public $vendors = [];

public function mount(): void
{
$this->vendors = [
'1' => 'Vendor 1',
'2' => 'Vendor 2',
'3' => 'Vendor 3',
];

$this->form->fill();
}

public function updateVendors(array $vendors)
{
$this->vendors = $vendors;
}

public function form(Form $form): Form
{
return $form
->schema([
Select::make('quickbooks_vendor_ref_id')
->label('Vendor')
->options(fn () => $this->vendors)
->preload()
->searchable()
->suffixAction(
Action::make('refreshVendors')
->label('Refresh Vendors')
->icon('heroicon-o-arrow-path')
->action(function (Select $component) {
$component->state(null);

$newVendors = [
'4' => 'Vendor 4',
'5' => 'Vendor 5',
'6' => 'Vendor 6',
];
$this->updateVendors($newVendors);
})
),
])
->statePath('data');
}
Jon Mason
Jon Mason2mo ago
@awcodes I have a select with options that are populated from an external api. I'm caching the results so it's not constantly fetching them. If a new item is added in this external software, I want to be able to click the refresh button to get a fresh list from the API and cache it. It's working, but you have to refresh the page to get the new options in the select. @Leandro Ferreira It's a livewire component. I'll try your suggestion.
LeandroFerreira
LeandroFerreira2mo ago
Should work ✌️
Jon Mason
Jon Mason2mo ago
thanks! These ideas aren't working for some reason. Here's some context in case that's helpful. The dropdown isn't updating unless I refresh the page. public function mount() { $this->location = SelectedLocation::get(); $this->vendors = $this->getVendors($this->location); $this->form->fill(); } //lives in a trait. public function getVendors(Location $location, $forceRefresh = false) { $key = $this->getCacheKeyForLocation(CacheKeys::VENDORS, $location->id); if ($forceRefresh) { Cache::forget($key); } return Cache::remember($key, null, function () { return LocationVendors::get($this->location)->pluck('display_name', 'quickbooks_vendor_ref_id')->toArray(); }); } public function updateVendors(array $vendors) { $this->vendors = $vendors; } public function form(Form $form): Form { return $form->schema([ Select::make('quickbooks_vendor_ref_id') ->required() ->label('Vendor') ->options($this->vendors) ->preload() ->searchable() ->inlineLabel() ->loadingMessage('Loading vendors...') ->suffixAction( Action::make('refreshVendors') ->label('Refresh Vendors') ->icon('heroicon-o-arrow-path') ->action(function (Select $component) { $component->state(null); $vendors = $this->getVendors($this->location, true); $this->updateVendors($vendors); $component->callAfterStateUpdated(); }) ), ])->statePath('data') ->model($this->item) ->disabled(fn () => in_array($this->item->document_status_id, [5, 6])); } also, not sure how you guys are getting the nice formatted code in discord..
MohamedSabil83
MohamedSabil832mo ago
Like following just clear space after (`): ` ` ` php // Put your code here ` ` `
Solution
MohamedSabil83
MohamedSabil832mo ago
use ->options(fn () => $this->vendors)
Jon Mason
Jon Mason2mo ago
that worked!! oh man, you're my hero. thanks!