mirror of
https://github.com/filamentphp/filament.git
synced 2026-08-29 03:09:12 +08:00
docs: #[ExposedLivewireMethod] (#19133)
This commit is contained in:
@@ -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
|
||||
{
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -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
|
||||
{
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user