feature: SPA mode URL exceptions

This commit is contained in:
Dan Harrin
2024-03-06 12:34:56 +00:00
parent ba50884499
commit 4a65396e04
6 changed files with 106 additions and 4 deletions
+38
View File
@@ -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:
+1
View File
@@ -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);
}
}
+11 -1
View File
@@ -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);
});
}
}
+32 -2
View File
@@ -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);
}
}
+1 -1
View File
@@ -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';
}