mirror of
https://github.com/filamentphp/filament.git
synced 2026-09-24 15:42:09 +08:00
Force render to bypass partial rendering (#17862)
* Skip partial rendering with forceRender * Add department schema * Test force render with create another in relation manager * chore: fix code style * Test force render with create another in relation manager * Move forceRender into InteractsWithActions * chore: fix code style * Early return dehydrate if force render * Add helper method to force render after create another * Update CreateAction.php --------- Co-authored-by: Dan Harrin <git@danharrin.com>
This commit is contained in:
@@ -332,6 +332,11 @@ trait InteractsWithActions
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function forceRender(): void
|
||||
{
|
||||
app(PartialsComponentHook::class)->forceRender($this);
|
||||
}
|
||||
|
||||
protected function partiallyRenderActionParentSchema(Action $action): void
|
||||
{
|
||||
$actionSchema = $action->getSchemaContainer() ?? $action->getSchemaComponent()?->getContainer();
|
||||
|
||||
@@ -23,6 +23,8 @@ class CreateAction extends Action
|
||||
|
||||
protected bool | Closure $canCreateAnother = true;
|
||||
|
||||
protected bool | Closure $shouldForceRenderAfterCreateAnother = false;
|
||||
|
||||
protected ?Closure $modifyCreateAnotherActionUsing = null;
|
||||
|
||||
protected ?Closure $preserveFormDataWhenCreatingAnotherUsing = null;
|
||||
@@ -107,6 +109,14 @@ class CreateAction extends Action
|
||||
$schema->model($record)->saveRelationships();
|
||||
|
||||
if ($arguments['another'] ?? false) {
|
||||
if ($this->shouldForceRenderAfterCreateAnother()) {
|
||||
$livewire = $this->getLivewire();
|
||||
|
||||
if (method_exists($livewire, 'forceRender')) {
|
||||
$livewire->forceRender();
|
||||
}
|
||||
}
|
||||
|
||||
$this->callAfter();
|
||||
$this->sendSuccessNotification();
|
||||
|
||||
@@ -157,6 +167,13 @@ class CreateAction extends Action
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function forceRenderAfterCreateAnother(bool | Closure $condition = true): static
|
||||
{
|
||||
$this->shouldForceRenderAfterCreateAnother = $condition;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use `createAnother()` instead.
|
||||
*/
|
||||
@@ -192,6 +209,11 @@ class CreateAction extends Action
|
||||
return true;
|
||||
}
|
||||
|
||||
public function shouldForceRenderAfterCreateAnother(): bool
|
||||
{
|
||||
return (bool) $this->evaluate($this->shouldForceRenderAfterCreateAnother);
|
||||
}
|
||||
|
||||
public function getRelationship(): Relation | Builder | null
|
||||
{
|
||||
return $this->evaluate($this->getRelationshipUsing) ?? $this->getTable()?->getRelationship() ?? $this->getHasActionsLivewire()?->getDefaultActionRelationship($this);
|
||||
|
||||
@@ -17,6 +17,10 @@ class PartialsComponentHook extends ComponentHook
|
||||
{
|
||||
public function shouldSkipRender(): bool
|
||||
{
|
||||
if ($this->shouldForceRender()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $this->isLackingPartialRendersToCoverAllCallsAndUpdates()) {
|
||||
return true;
|
||||
}
|
||||
@@ -62,6 +66,11 @@ class PartialsComponentHook extends ComponentHook
|
||||
return ($updatesCount + $callsCount) !== intval($this->storeGet('partialRendersCount') ?? 0);
|
||||
}
|
||||
|
||||
public function shouldForceRender(): bool
|
||||
{
|
||||
return store($this->component)->get('forceRender', false);
|
||||
}
|
||||
|
||||
public function shouldRenderMountedActionOnly(): bool
|
||||
{
|
||||
if (! property_exists($this->component, 'mountedActions')) {
|
||||
@@ -100,6 +109,10 @@ class PartialsComponentHook extends ComponentHook
|
||||
|
||||
public function dehydrate(ComponentContext $context): void
|
||||
{
|
||||
if ($this->shouldForceRender()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$partials = [];
|
||||
|
||||
$renderAndQueuePartials = function (Closure $getPartialsUsing) use (&$partials): void {
|
||||
@@ -173,6 +186,11 @@ class PartialsComponentHook extends ComponentHook
|
||||
$this->recordPartialRender($component);
|
||||
}
|
||||
|
||||
public function forceRender(Component $component, bool $forceRender = true): void
|
||||
{
|
||||
store($component)->set('forceRender', $forceRender);
|
||||
}
|
||||
|
||||
public function renderPartial(Component $component, Closure $renderUsing): void
|
||||
{
|
||||
store($component)->push('partials', $renderUsing);
|
||||
|
||||
@@ -13,6 +13,8 @@ class Department extends Model
|
||||
use HasFactory;
|
||||
use SoftDeletes;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
protected static function newFactory()
|
||||
{
|
||||
return DepartmentFactory::new();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Filament\Tests\Fixtures\Resources\Departments\Schemas;
|
||||
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Schemas\Schema;
|
||||
|
||||
class DepartmentForm
|
||||
@@ -10,7 +11,7 @@ class DepartmentForm
|
||||
{
|
||||
return $schema
|
||||
->components([
|
||||
//
|
||||
TextInput::make('name')->required(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@ namespace Filament\Tests\Fixtures\Resources\Tickets\RelationManagers;
|
||||
|
||||
use Filament\Actions\CreateAction;
|
||||
use Filament\Resources\RelationManagers\RelationManager;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Tables\Table;
|
||||
use Filament\Tests\Fixtures\Resources\Departments\Schemas\DepartmentForm;
|
||||
use Filament\Tests\Fixtures\Resources\Departments\Tables\DepartmentsTable;
|
||||
|
||||
class DepartmentsRelationManager extends RelationManager
|
||||
@@ -18,4 +20,9 @@ class DepartmentsRelationManager extends RelationManager
|
||||
CreateAction::make(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function form(Schema $schema): Schema
|
||||
{
|
||||
return DepartmentForm::configure($schema);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ use Filament\Actions\RestoreAction;
|
||||
use Filament\Actions\RestoreBulkAction;
|
||||
use Filament\Actions\Testing\TestAction;
|
||||
use Filament\Actions\ViewAction;
|
||||
use Filament\Resources\RelationManagers\RelationManager;
|
||||
use Filament\Tests\Fixtures\Models\Department;
|
||||
use Filament\Tests\Fixtures\Models\Ticket;
|
||||
use Filament\Tests\Fixtures\Policies\DepartmentPolicy;
|
||||
@@ -18,8 +19,10 @@ use Filament\Tests\Fixtures\Resources\Tickets\Pages\EditTicket;
|
||||
use Filament\Tests\Fixtures\Resources\Tickets\RelationManagers\DepartmentsRelationManager;
|
||||
use Filament\Tests\Panels\Resources\TestCase;
|
||||
use Illuminate\Auth\Access\Response;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
use function Filament\Tests\livewire;
|
||||
use function Pest\Laravel\assertDatabaseHas;
|
||||
|
||||
uses(TestCase::class);
|
||||
|
||||
@@ -150,3 +153,29 @@ it('renders actions based on policy', function (string $action, string $policyMe
|
||||
'restore bulk action with policy returning allowed response' => fn (): array => [RestoreBulkAction::class, 'restoreAny', Response::allow(), true, true, true],
|
||||
'restore bulk action with policy returning false' => fn (): array => [RestoreBulkAction::class, 'restoreAny', false, false, true, true],
|
||||
'restore bulk action with policy returning denied response' => fn (): array => [RestoreBulkAction::class, 'restoreAny', Response::deny(), false, true, true]]);
|
||||
|
||||
it('can force render relation manager after create another', function (): void {
|
||||
$ticket = Ticket::factory()
|
||||
->create();
|
||||
|
||||
CreateAction::configureUsing(function (CreateAction $action): void {
|
||||
$action->forceRenderAfterCreateAnother(fn (mixed $livewire): bool => $livewire instanceof RelationManager);
|
||||
});
|
||||
|
||||
$action = TestAction::make(CreateAction::class)->table();
|
||||
|
||||
livewire(DepartmentsRelationManager::class, ['ownerRecord' => $ticket, 'pageClass' => EditTicket::class])
|
||||
->assertSuccessful()
|
||||
->assertCountTableRecords(0)
|
||||
->assertActionExists($action)
|
||||
->mountAction($action, ['another' => true])
|
||||
->fillForm([
|
||||
'name' => $name = Str::random(),
|
||||
])
|
||||
->callMountedAction()
|
||||
->assertHasNoFormErrors()
|
||||
->assertCountTableRecords(1)
|
||||
->assertSeeText($name);
|
||||
|
||||
assertDatabaseHas(Department::class, ['name' => $name]);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user