mirror of
https://github.com/filamentphp/filament.git
synced 2026-10-28 02:32:58 +08:00
feature: SPA mode URL exceptions
This commit is contained in:
@@ -147,6 +147,44 @@ public function panel(Panel $panel): Panel
|
||||
}
|
||||
```
|
||||
|
||||
### Disabling SPA navigation for specific URLs
|
||||
|
||||
By default, when enabling SPA mode, any URL that lives on the same domain as the current request will be navigated to using Livewire's [`wire:navigate`](https://livewire.laravel.com/docs/navigate) feature. If you want to disable this for specific URLs, you can use the `spaUrlExceptions()` method:
|
||||
|
||||
```php
|
||||
use App\Filament\Resources\PostResource;
|
||||
use Filament\Panel;
|
||||
|
||||
public function panel(Panel $panel): Panel
|
||||
{
|
||||
return $panel
|
||||
// ...
|
||||
->spa()
|
||||
->spaUrlExceptions(fn (): array => [
|
||||
url('/admin'),
|
||||
PostResource::getUrl(),
|
||||
]);
|
||||
}
|
||||
```
|
||||
|
||||
> In this example, we are using [`getUrl()`](/resources/getting-started#generating-urls-to-resource-pages) on a resource to get the URL to the resource's index page. This feature requires the panel to already be registered though, and the configuration is too early in the request lifecycle to do that. You can use a function to return the URLs instead, which will be resolved when the panel has been registered.
|
||||
|
||||
These URLs need to exactly match the URL that the user is navigating to, including the domain and protocol. If you'd like to use a pattern to match multiple URLs, you can use an asterisk (`*`) as a wildcard character:
|
||||
|
||||
```php
|
||||
use Filament\Panel;
|
||||
|
||||
public function panel(Panel $panel): Panel
|
||||
{
|
||||
return $panel
|
||||
// ...
|
||||
->spa()
|
||||
->spaUrlExceptions([
|
||||
'*/admin/posts/*',
|
||||
]);
|
||||
}
|
||||
```
|
||||
|
||||
## Unsaved changes alerts
|
||||
|
||||
You may alert users if they attempt to navigate away from a page without saving their changes. This is applied on [Create](resources/creating-records) and [Edit](resources/editing-records) pages of a resource, as well as any open action modals. To enable this feature, you can use the `unsavedChangesAlerts()` method:
|
||||
|
||||
@@ -77,6 +77,7 @@ class Panel extends Component
|
||||
FilamentIcon::register($this->getIcons());
|
||||
|
||||
FilamentView::spa($this->hasSpaMode());
|
||||
FilamentView::spaUrlExceptions($this->getSpaUrlExceptions());
|
||||
|
||||
$this->registerRenderHooks();
|
||||
|
||||
|
||||
@@ -8,6 +8,11 @@ trait HasSpaMode
|
||||
{
|
||||
protected bool | Closure $hasSpaMode = false;
|
||||
|
||||
/**
|
||||
* @var array<string> | Closure
|
||||
*/
|
||||
protected array | Closure $spaModeUrlExceptions = [];
|
||||
|
||||
public function spa(bool | Closure $condition = true): static
|
||||
{
|
||||
$this->hasSpaMode = $condition;
|
||||
@@ -15,8 +20,26 @@ trait HasSpaMode
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string>| Closure $exceptions
|
||||
*/
|
||||
public function spaUrlExceptions(array | Closure $exceptions): static
|
||||
{
|
||||
$this->spaModeUrlExceptions = $exceptions;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasSpaMode(): bool
|
||||
{
|
||||
return (bool) $this->evaluate($this->hasSpaMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string>
|
||||
*/
|
||||
public function getSpaUrlExceptions(): array
|
||||
{
|
||||
return $this->evaluate($this->spaModeUrlExceptions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use Illuminate\Contracts\Support\Htmlable;
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
|
||||
/**
|
||||
* @method static bool hasSpaMode()
|
||||
* @method static bool hasSpaMode(?string $url = null)
|
||||
* @method static Htmlable renderHook(string $name, string | array | null $scopes = null)
|
||||
*
|
||||
* @see ViewManager
|
||||
@@ -36,4 +36,14 @@ class FilamentView extends Facade
|
||||
$viewManager->spa($condition);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string> $exceptions
|
||||
*/
|
||||
public static function spaUrlExceptions(array $exceptions): void
|
||||
{
|
||||
static::resolved(function (ViewManager $viewManager) use ($exceptions) {
|
||||
$viewManager->spaUrlExceptions($exceptions);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ use Illuminate\Contracts\Support\Htmlable;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\HtmlString;
|
||||
|
||||
use function Filament\Support\is_app_url;
|
||||
|
||||
class ViewManager
|
||||
{
|
||||
/**
|
||||
@@ -16,6 +18,11 @@ class ViewManager
|
||||
|
||||
protected bool $hasSpaMode = false;
|
||||
|
||||
/**
|
||||
* @var array<string>
|
||||
*/
|
||||
protected array $spaModeUrlExceptions = [];
|
||||
|
||||
/**
|
||||
* @param string | array<string> | null $scopes
|
||||
*/
|
||||
@@ -74,8 +81,31 @@ class ViewManager
|
||||
$this->hasSpaMode = $condition;
|
||||
}
|
||||
|
||||
public function hasSpaMode(): bool
|
||||
/**
|
||||
* @param array<string> $exceptions
|
||||
*/
|
||||
public function spaUrlExceptions(array $exceptions): void
|
||||
{
|
||||
return $this->hasSpaMode;
|
||||
$this->spaModeUrlExceptions = [
|
||||
...$this->spaModeUrlExceptions,
|
||||
...$exceptions,
|
||||
];
|
||||
}
|
||||
|
||||
public function hasSpaMode(?string $url = null): bool
|
||||
{
|
||||
if (! $this->hasSpaMode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (blank($url)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (count($this->spaModeUrlExceptions) && str($url)->is($this->spaModeUrlExceptions)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return is_app_url($url);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ if (! function_exists('Filament\Support\generate_href_html')) {
|
||||
|
||||
if ($shouldOpenInNewTab) {
|
||||
$html .= ' target="_blank"';
|
||||
} elseif ($shouldOpenInSpaMode ?? (FilamentView::hasSpaMode() && is_app_url($url))) {
|
||||
} elseif ($shouldOpenInSpaMode ?? (FilamentView::hasSpaMode($url))) {
|
||||
$html .= ' wire:navigate';
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user