F
Filament6mo ago
Fossil

Header action modal to search API, how to show results properly?

So I have a header action which opens a modal. The modal houses a form field which allows you to search an external API. I process the results in the ->action(function (array $data) {} method. Now I want to loop over the results and build a nice HTML table or something so a user can pick a result. However I when I do var_dump($data); I get nothing. When I do dd($data) I see my data in a black dd() screen of course so it's there. Any way of presenting this data to this or another modal and fire some PHP code when a user clicks a result?
\Filament\Actions\Action::make('searchapi')
->label('Search')
->icon('heroicon-o-arrow-path')
->color('info')
->form([
TextInput::make('title')->required(),
])
->action(function (array $data) {
// Call external API here with $data['title'] and put result in $results
var_dump($results); // Nothing. Just shows loading spinner on TextInput Submit button
}),
\Filament\Actions\Action::make('searchapi')
->label('Search')
->icon('heroicon-o-arrow-path')
->color('info')
->form([
TextInput::make('title')->required(),
])
->action(function (array $data) {
// Call external API here with $data['title'] and put result in $results
var_dump($results); // Nothing. Just shows loading spinner on TextInput Submit button
}),
Solution:
Oh that might work. Never used it before so I will read the docs. Cheers
Jump to solution
16 Replies
toeknee
toeknee6mo ago
action is handled on submitting the form and it would return title. What you probably want is to use the wizard plugin by using ->steps() and add a step into it called 'Search' and another step 'Selection' which would be a custom livewire component populating data from step 1.
Solution
Fossil
Fossil6mo ago
Oh that might work. Never used it before so I will read the docs. Cheers
toeknee
toeknee6mo ago
No problem!
Fossil
Fossil6mo ago
I could not find this in the docs but how do I pass data from one step to another?
->steps([
Step::make('Search')
->description('Search blahblah')
->schema([
TextInput::make('name')
->required()
]),
Step::make('Select')
->description('Select one of the results'),
Step::make('Visibility')
->description('Control who can view it')
->schema([
TextInput::make('description'),
]),
]),
->steps([
Step::make('Search')
->description('Search blahblah')
->schema([
TextInput::make('name')
->required()
]),
Step::make('Select')
->description('Select one of the results'),
Step::make('Visibility')
->description('Control who can view it')
->schema([
TextInput::make('description'),
]),
]),
Like I want to call $results = $someClass->search($name); when they complete Step1 and click NEXT and then have $results in Step 2.
toeknee
toeknee6mo ago
With closures , so you could do afterStateUpdated i.e.
->steps([
Step::make('Search')
->description('Search blahblah')
->schema([
TextInput::make('name')
->required()
])
->afterStateUpdated(fn(\Closure $get, $set) => $set('my_select', MyModel::where('name', 'LIKE', '%' . $get('Search') . '%' )),
Step::make('Select')
->schema([
Select::make('name')
->options([])
->required()
])
->description('Select one of the results'),
Step::make('Visibility')
->description('Control who can view it')
->schema([
TextInput::make('description'),
]),
]),
->steps([
Step::make('Search')
->description('Search blahblah')
->schema([
TextInput::make('name')
->required()
])
->afterStateUpdated(fn(\Closure $get, $set) => $set('my_select', MyModel::where('name', 'LIKE', '%' . $get('Search') . '%' )),
Step::make('Select')
->schema([
Select::make('name')
->options([])
->required()
])
->description('Select one of the results'),
Step::make('Visibility')
->description('Control who can view it')
->schema([
TextInput::make('description'),
]),
]),
Fossil
Fossil6mo ago
Ahh ok. Will try. Tnx Property type not supported in Livewire for property: [{}] I have no clue where that comes from or what it means lol
toeknee
toeknee6mo ago
Please provide a copy of your code.
Fossil
Fossil6mo ago
Action::make('search_imdb')
->label('Search IMDB')
->icon('heroicon-o-arrow-path')
->color('info')
->steps([
Step::make('search')
->description('Search blahblah')
->schema([
TextInput::make('title')
->required(),
])
->afterStateUpdated(function (Get $get, Set $set) {
$omdb = new OMDbAPI(config('nntmux_api.omdb_api_key'));
$result = $omdb->search($get('title'), 'movie');
foreach ($result->data->Search as $movie) {
$movies[] = [
'title' => $movie->Title,
'year' => $movie->Year,
'imdbid' => $movie->imdbID,
'poster' => $movie->Poster,
];
}
$set('omdb_result', $movies);

}),
Step::make('Select')
->description('Select one of the results')
->schema([
// Show table with results
omdbResults::make()->viewData([
'omdb_result' => ['test' => 123456],
]),
]),
]),
Action::make('search_imdb')
->label('Search IMDB')
->icon('heroicon-o-arrow-path')
->color('info')
->steps([
Step::make('search')
->description('Search blahblah')
->schema([
TextInput::make('title')
->required(),
])
->afterStateUpdated(function (Get $get, Set $set) {
$omdb = new OMDbAPI(config('nntmux_api.omdb_api_key'));
$result = $omdb->search($get('title'), 'movie');
foreach ($result->data->Search as $movie) {
$movies[] = [
'title' => $movie->Title,
'year' => $movie->Year,
'imdbid' => $movie->imdbID,
'poster' => $movie->Poster,
];
}
$set('omdb_result', $movies);

}),
Step::make('Select')
->description('Select one of the results')
->schema([
// Show table with results
omdbResults::make()->viewData([
'omdb_result' => ['test' => 123456],
]),
]),
]),
Hmm I can access $omdb_result in the view but when I try to get $set('omdb_result', $movies); this one I get htmlspecialchars(): Argument #1 ($string) must be of type string, Closure given
omdbResults::make()->viewData([
'result' => fn (Get $get) => $get('omdb_result'),
]),
omdbResults::make()->viewData([
'result' => fn (Get $get) => $get('omdb_result'),
]),
This doesn't seem to work either Seems you cant pass data between Steps Any idea @toeknee
toeknee
toeknee6mo ago
viewData doesn't allow closures. You should be able to get the forms state within the view. with $getState or similar. You'll need to double check that one on the docs. I got it working a while ago but haven't done it since
Fossil
Fossil6mo ago
So I can get the value of something in afterStateUpdated() from the previous step in the view? Cant find anything about sharing data between steps
toeknee
toeknee6mo ago
Sorry for the delay, you can get the entire livewire data from within the view already, I think it's something like $getState which has all the data?
Fossil
Fossil6mo ago
I am an idiot. I ran $getState but not the function $getState() Would it be possible to then take a value from the modal and populate a form field in the original Filament Edit page with that? Even just calling the Eloquent model and then save it from the modal would work. Like $getRecord()->name = 'Blah' and $getRecord()->save()
toeknee
toeknee6mo ago
Yeah you should be able to pass them back and forth with V3 if I understand you correctly, there should be a parent action for example now
Fossil
Fossil2mo ago
Taking another go at this. The following works and I get data in $movie. I need the $movie['imdbid'] to be either pushed back to the Filament Edit page, or it should just directly update the model with the new value.
@foreach ($getState()['movies'] as $movie)
<button type="button">Save</button>
@endforeach
@foreach ($getState()['movies'] as $movie)
<button type="button">Save</button>
@endforeach
I just have no clue why. I tried calling a method on EditRelease.php with wire:click but that doesn't do anything. I can access the model with $getRecord() but there is no $setRecord 😛 I am trying wire:emit now but getting Unable to call component method. Public method [$emit] not found on component Ok I made it work by just calling a public function on the Filament EditRecord class