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
LeandroFerreira6mo 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
javiersalcedoj6mo 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.
Want results from more Discord servers?
Add your server