Calling `callMountedFormComponentAction` with arguments does not pass the arguments
Package
filament/filament
Package Version
v3.2
Laravel Version
v10.0
Livewire Version
v3.x
PHP Version
PHP8.2
Problem description
I have upgraded my Filament app from v3.0.62 to v3.2.x and I am facing following problem.
Problem:
I have added an Action to hintAction, It renders a custom Livewire component inside the action's modal.
->modalContent(fn ($record) => new HtmlString(Blade::render("@livewire('name-generator')")))
Inside the Livewire name-generator, i'm able to call
$wire.$parent.callMountedFormComponentAction(@js(['name' => $name]))
And this calls the mountedAction as expected
->action(function (Set $set, $component, $arguments)
However the injected $arguments is always an empty array.
The possible culprit
Seems like this is happening after this specific commit? https://github.com/filamentphp/filament/commit/a198bd1acea3d5c40ee564cf5d26055c6f23e59e
Expected behavior
By calling $wire.$parent.callMountedFormComponentAction() which calls the mountedAction ->action(function (Set $set, $component, $arguments), the $arguments variable should contain the arguments passed in callMountedFormComponentAction.
Which works in v3.0.62 but fails in new versions like v3.2.x.
Steps to reproduce
Lets say we want to generate a name using an API. We need to show a Modal which lists a few names that can be selected by clicking.
Skip reading steps by directly reviewing the Reproduction commit: https://github.com/mansoorkhan96/filament-playground/commit/87dc7eff24c50658cefc66b6cb7b23ba4e2d3720
Step 1
Add a Form Action to hintAction:
Forms\Components\TextInput::make('name')
->hintAction(
Action::make('generate-name')
->modalSubmitAction(fn (StaticAction $action) => $action->hidden())
->modalContent(fn ($record) => new HtmlString(Blade::render("@livewire('name-generator')")))
->action(function (Set $set, $record, $arguments) {
$set('name', $arguments['name']);
})
)
Step 2
Create NameGenerator Livewire component which should show the generated names list.
class NameGenerator extends Component
{
public $aiGeneratedNames = [
'John',
'Jane',
'Bob',
];
public function render()
{
return view('livewire.name-generator');
}
}
// blade file
<ul class="flex flex-col gap-2">
@foreach ($aiGeneratedNames as $name)
<li
class="cursor-pointer"
@click="$wire.$parent.callMountedFormComponentAction(@js(['name' => $name]))"
>
{{ $name }}
</li>
@endforeach
</ul>
Step 3
Now inside browser, clicking on the hint action generate-name should open a modal with the names list. Click on any name.
Actual behaviour
Clicking on name throws an ErrorException Undefined array key "name" which means the $arguments is empty and the $wire.$parent.callMountedFormComponentAction(@js(['name' => $name])) never passed the data.
Expected behaviour
Clicking on name should set name field to selected name without any Error/Exception.
Reproduction repository
https://github.com/mansoorkhan96/filament-playground
Relevant log output
No response
I tried to debug this and seems like the Action arguments are flushed out when following methods are called in HasFormComponentActions Trait:
getMountedFormComponentActionForm
// Line No: 57
$form = $this->getMountedFormComponentActionForm();
mountedFormComponentActionHasForm
// Line No: 62
if ($this->mountedFormComponentActionHasForm()) {
}
$action->mergeArguments($arguments); is called on Line: 55 and then after that, both of the above mentioned method calls flush out the arguments. If you dd($action->getArguments()) after any of the above method call, its an empty array. However, if you add the $action->mergeArguments($arguments); on Line: 69 again, It works and the arguments are successfully passed to ->action() method of the Action.
$action->mergeArguments($arguments); // here
$action->callBefore();
$result = $action->call([
'form' => $form,
]);
@zepfietje @danharrin Should I send a PR to move down the $action->mergeArguments($arguments); and call it after the above mentioned methods? I am not quite sure if the arguments are also passed to LifecycleHook methods like: beforeFormValidated, afterFormValidated, before, etc.
Hey @danharrin Could you please help me what could be a work around for now.
Maybe some other way to handle this kind of requirement?
This was actually the next item on my Issues todo list, but each time the author @s me it kinda makes me not want to deal with it 😅 please be patient
I apologise for not being patient. Thanks for taking time ❤️
Thank you so much for fixing this one.