docs: #[ExposedLivewireMethod] (#19133)

This commit is contained in:
Dan Harrin
2026-01-29 17:53:47 +00:00
committed by GitHub
parent 8336fc4924
commit 5256ec2138
3 changed files with 301 additions and 4 deletions
+93 -2
View File
@@ -253,11 +253,102 @@ Filament provides a `$applyStateBindingModifiers()` function that you may use in
:field="$field"
>
<input {{ $applyStateBindingModifiers('wire:model') }}="{{ $getStatePath() }}" />
<!-- Or -->
<div x-data="{ state: $wire.{{ $applyStateBindingModifiers("\$entangle('{$getStatePath()}')") }} }">
<input x-model="state" />
</div>
</x-dynamic-component>
```
## Calling field methods from JavaScript
Sometimes you need to call a method on the field class from JavaScript in the Blade view. For example, you might want to fetch data asynchronously, process a file upload, or perform some server-side computation. Filament provides a way to expose methods on your field class to JavaScript using the `#[ExposedLivewireMethod]` attribute.
### Exposing a method
To expose a method to JavaScript, add the `#[ExposedLivewireMethod]` attribute to a public method on your custom field class:
```php
use Filament\Forms\Components\Field;
use Filament\Support\Components\Attributes\ExposedLivewireMethod;
class LocationPicker extends Field
{
protected string $view = 'filament.forms.components.location-picker';
#[ExposedLivewireMethod]
public function geocodeAddress(string $address): array
{
// Perform geocoding logic...
return [
'latitude' => $latitude,
'longitude' => $longitude,
];
}
}
```
<Aside variant="info">
Only methods marked with `#[ExposedLivewireMethod]` can be called from JavaScript. This is a security measure to prevent arbitrary method execution.
</Aside>
### Calling the method from JavaScript
In your Blade view, you may call the exposed method using `$wire.callSchemaComponentMethod()`. The first argument is the component's key (available via `$getKey()`), and the second argument is the method name. You may pass arguments as a third argument:
```blade
@php
$key = $getKey();
@endphp
<x-dynamic-component
:component="$getFieldWrapperView()"
:field="$field"
>
<div
x-data="{
address: '',
coordinates: null,
async geocode() {
this.coordinates = await $wire.callSchemaComponentMethod(
@js($key),
'geocodeAddress',
{ address: this.address },
)
},
}"
>
<input type="text" x-model="address" />
<button type="button" x-on:click="geocode">Geocode</button>
<template x-if="coordinates">
<p x-text="`${coordinates.latitude}, ${coordinates.longitude}`"></p>
</template>
</div>
</x-dynamic-component>
```
### Preventing re-renders
By default, calling an exposed method will trigger a re-render of the Livewire component. If your method doesn't need to update the UI, you may add Livewire's `#[Renderless]` attribute alongside `#[ExposedLivewireMethod]` to skip the re-render:
```php
use Filament\Forms\Components\Field;
use Filament\Support\Components\Attributes\ExposedLivewireMethod;
use Livewire\Attributes\Renderless;
class LocationPicker extends Field
{
protected string $view = 'filament.forms.components.location-picker';
#[ExposedLivewireMethod]
#[Renderless]
public function geocodeAddress(string $address): array
{
// ...
}
}
```
@@ -209,3 +209,87 @@ use App\Filament\Infolists\Components\AudioPlayerEntry;
AudioPlayerEntry::make('recording')
->speed(fn (Conference $record): float => $record->isGlobal() ? 1 : 0.5)
```
## Calling entry methods from JavaScript
Sometimes you need to call a method on the entry class from JavaScript in the Blade view. For example, you might want to fetch data asynchronously or perform some server-side computation. Filament provides a way to expose methods on your entry class to JavaScript using the `#[ExposedLivewireMethod]` attribute.
### Exposing a method
To expose a method to JavaScript, add the `#[ExposedLivewireMethod]` attribute to a public method on your custom entry class:
```php
use Filament\Infolists\Components\Entry;
use Filament\Support\Components\Attributes\ExposedLivewireMethod;
class AudioPlayerEntry extends Entry
{
protected string $view = 'filament.infolists.components.audio-player-entry';
#[ExposedLivewireMethod]
public function getWaveformData(): array
{
// Generate waveform data from the audio file...
return $waveformData;
}
}
```
<Aside variant="info">
Only methods marked with `#[ExposedLivewireMethod]` can be called from JavaScript. This is a security measure to prevent arbitrary method execution.
</Aside>
### Calling the method from JavaScript
In your Blade view, you may call the exposed method using `$wire.callSchemaComponentMethod()`. The first argument is the component's key (available via `$getKey()`), and the second argument is the method name. You may pass arguments as a third argument:
```blade
@php
$key = $getKey();
@endphp
<x-dynamic-component
:component="$getEntryWrapperView()"
:entry="$entry"
>
<div
x-data="{
waveform: null,
async loadWaveform() {
this.waveform = await $wire.callSchemaComponentMethod(
@js($key),
'getWaveformData',
)
},
}"
x-init="loadWaveform"
>
<template x-if="waveform">
{{-- Render the waveform visualization --}}
</template>
</div>
</x-dynamic-component>
```
### Preventing re-renders
By default, calling an exposed method will trigger a re-render of the Livewire component. If your method doesn't need to update the UI, you may add Livewire's `#[Renderless]` attribute alongside `#[ExposedLivewireMethod]` to skip the re-render:
```php
use Filament\Infolists\Components\Entry;
use Filament\Support\Components\Attributes\ExposedLivewireMethod;
use Livewire\Attributes\Renderless;
class AudioPlayerEntry extends Entry
{
protected string $view = 'filament.infolists.components.audio-player-entry';
#[ExposedLivewireMethod]
#[Renderless]
public function getWaveformData(): array
{
// ...
}
}
```
+124 -2
View File
@@ -363,7 +363,7 @@ use Filament\Schemas\Components\Component;
class Chart extends Component
{
protected string $view = 'filament.schemas.components.chart';
protected string | Closure | null $heading = null;
public function __construct(string | Closure | null $heading = null)
@@ -375,7 +375,7 @@ class Chart extends Component
{
return app(static::class, ['heading' => $heading]);
}
public function heading(string | Closure | null $heading): static
{
$this->heading = $heading;
@@ -389,3 +389,125 @@ class Chart extends Component
}
}
```
### Calling component methods from JavaScript
Sometimes you need to call a method on the component class from JavaScript in the Blade view. For example, you might want to fetch data asynchronously or perform some server-side computation. Filament provides a way to expose methods on your component class to JavaScript using the `#[ExposedLivewireMethod]` attribute.
#### Exposing a method
To expose a method to JavaScript, add the `#[ExposedLivewireMethod]` attribute to a public method on your custom component class:
```php
use Filament\Schemas\Components\Component;
use Filament\Support\Components\Attributes\ExposedLivewireMethod;
class Chart extends Component
{
protected string $view = 'filament.schemas.components.chart';
public static function make(): static
{
return app(static::class);
}
#[ExposedLivewireMethod]
public function getChartData(): array
{
// Fetch and process chart data...
return $chartData;
}
}
```
<Aside variant="info">
Only methods marked with `#[ExposedLivewireMethod]` can be called from JavaScript. This is a security measure to prevent arbitrary method execution.
</Aside>
#### Calling the method from JavaScript
In your Blade view, you may call the exposed method using `$wire.callSchemaComponentMethod()`. The first argument is the component's key (available via `$getKey()`), and the second argument is the method name. You may pass arguments as a third argument:
```blade
@php
$key = $getKey();
@endphp
<div
x-data="{
data: null,
async loadData() {
this.data = await $wire.callSchemaComponentMethod(
@js($key),
'getChartData',
)
},
}"
x-init="loadData"
>
<template x-if="data">
{{-- Render the chart using the data --}}
</template>
</div>
```
You may pass arguments to the method by providing an object as the third argument:
```blade
@php
$key = $getKey();
@endphp
<div
x-data="{
data: null,
dateRange: 'week',
async loadData() {
this.data = await $wire.callSchemaComponentMethod(
@js($key),
'getChartData',
{ dateRange: this.dateRange },
)
},
}"
x-init="loadData"
>
<select x-model="dateRange" x-on:change="loadData">
<option value="week">This Week</option>
<option value="month">This Month</option>
<option value="year">This Year</option>
</select>
<template x-if="data">
{{-- Render the chart using the data --}}
</template>
</div>
```
#### Preventing re-renders
By default, calling an exposed method will trigger a re-render of the Livewire component. If your method doesn't need to update the UI, you may add Livewire's `#[Renderless]` attribute alongside `#[ExposedLivewireMethod]` to skip the re-render:
```php
use Filament\Schemas\Components\Component;
use Filament\Support\Components\Attributes\ExposedLivewireMethod;
use Livewire\Attributes\Renderless;
class Chart extends Component
{
protected string $view = 'filament.schemas.components.chart';
public static function make(): static
{
return app(static::class);
}
#[ExposedLivewireMethod]
#[Renderless]
public function getChartData(): array
{
// ...
}
}
```