How to Execute a Function on Button Click and Component Render in Custom Filament Fields?

Hi, I am creating custom fields and want to include a button that, when clicked, executes a function in my component. The function, sendOtp, queries the database and calls services, etc. Additionally, I want to call this function when the component is rendered for the first time. Here is my base code: Component:
<?php

namespace App\Forms\Components\Fields;

use Filament\Forms\Components\Field;

class AuthField extends Field
{
protected string $view = 'forms.components.fields.auth-field';

public function sendOtp(): void
{
// send otp logic
ray('send otp');
}
}
<?php

namespace App\Forms\Components\Fields;

use Filament\Forms\Components\Field;

class AuthField extends Field
{
protected string $view = 'forms.components.fields.auth-field';

public function sendOtp(): void
{
// send otp logic
ray('send otp');
}
}
Blade:
<x-dynamic-component
:component="$getFieldWrapperView()"
:field="$field"
>
<div
x-data="{
state: $wire.$entangle('{{ $getStatePath() }}'),
}"
x-init="sendOtp"
>
<input x-model="state" type="text" maxlength="6" minlength="6" placeholder="000000">

<button type="button">
Send OTP
</button>
</div>
</x-dynamic-component>
<x-dynamic-component
:component="$getFieldWrapperView()"
:field="$field"
>
<div
x-data="{
state: $wire.$entangle('{{ $getStatePath() }}'),
}"
x-init="sendOtp"
>
<input x-model="state" type="text" maxlength="6" minlength="6" placeholder="000000">

<button type="button">
Send OTP
</button>
</div>
</x-dynamic-component>
How can I make the button execute the sendOtp function on click, and also call this function when the component is rendered for the first time?
Solution:
Hi, To achieve your goal of creating a custom field with a button that executes the sendOtp function when clicked and also calls this function when the component is rendered for the first time, you can follow these steps: Component:...
Jump to solution
2 Replies
LeandroFerreira
LeandroFerreira8mo ago
sendOpt method should exist in the pages, in your CreatePage, EditPage... another way would be registering actions in the field https://filamentphp.com/docs/3.x/forms/actions/#adding-an-action-to-a-custom-form-component
Solution
javiersalcedoj
javiersalcedoj8mo ago
Hi, To achieve your goal of creating a custom field with a button that executes the sendOtp function when clicked and also calls this function when the component is rendered for the first time, you can follow these steps: Component: First, make sure to set up the action in your AuthField class:
namespace App\Forms\Components\Fields;

use Filament\Forms\Components\Field;
use Filament\Forms\Components\Actions\Action;

class AuthField extends Field
{
protected string $view = 'forms.components.fields.auth-field';

protected function setUp(): void
{
parent::setUp();

$this->registerActions([
Action::make('sendOtp')
->label('Send OTP')
->action(fn () => $this->sendOtp()),
]);
}

public function sendOtp(): void
{
// Send OTP logic
ray('send otp');
}
}
namespace App\Forms\Components\Fields;

use Filament\Forms\Components\Field;
use Filament\Forms\Components\Actions\Action;

class AuthField extends Field
{
protected string $view = 'forms.components.fields.auth-field';

protected function setUp(): void
{
parent::setUp();

$this->registerActions([
Action::make('sendOtp')
->label('Send OTP')
->action(fn () => $this->sendOtp()),
]);
}

public function sendOtp(): void
{
// Send OTP logic
ray('send otp');
}
}
Blade: Then, update your Blade template to call the sendOtp function when the button is clicked and when the component is initialized:
<x-dynamic-component
:component="$getFieldWrapperView()"
:field="$field"
>
<div
x-data="{
state: $wire.$entangle('{{ $getStatePath() }}'),
sendOtp() {
$wire.mountFormComponentAction('{{ $getStatePath() }}', 'sendOtp')
}
}"
x-init="sendOtp"
>
<input x-model="state" type="text" maxlength="6" minlength="6" placeholder="000000">

<button type="button" @click="sendOtp">
Send OTP
</button>
</div>
</x-dynamic-component>
<x-dynamic-component
:component="$getFieldWrapperView()"
:field="$field"
>
<div
x-data="{
state: $wire.$entangle('{{ $getStatePath() }}'),
sendOtp() {
$wire.mountFormComponentAction('{{ $getStatePath() }}', 'sendOtp')
}
}"
x-init="sendOtp"
>
<input x-model="state" type="text" maxlength="6" minlength="6" placeholder="000000">

<button type="button" @click="sendOtp">
Send OTP
</button>
</div>
</x-dynamic-component>
With these changes, the sendOtp function will be called both when the component is rendered initially and when the button is clicked.

Did you find this page helpful?