diff --git a/src/Broadcasting/PendingBroadcast.php b/src/Broadcasting/PendingBroadcast.php index c326bfe..0da7d75 100644 --- a/src/Broadcasting/PendingBroadcast.php +++ b/src/Broadcasting/PendingBroadcast.php @@ -134,7 +134,12 @@ public function toOthers(bool $toOthers = true): self public function partial(?string $partial, array $data = []): self { - return $this->rendering(new Rendering($partial, $data)); + return $this->view($partial, $data); + } + + public function view(?string $view, array $data = []): self + { + return $this->rendering(new Rendering($view, $data)); } public function content($content) diff --git a/src/Commands/TurboInstallCommand.php b/src/Commands/TurboInstallCommand.php index 59e783a..5a42503 100644 --- a/src/Commands/TurboInstallCommand.php +++ b/src/Commands/TurboInstallCommand.php @@ -121,7 +121,7 @@ private function updateImportmapsDependencies(): void private function jsDependencies(): array { return [ - '@hotwired/turbo' => '^8.0.3', + '@hotwired/turbo' => '^8.0.4', 'laravel-echo' => '^1.15.0', 'pusher-js' => '^8.0.1', ]; diff --git a/src/Models/Broadcasts.php b/src/Models/Broadcasts.php index a375e72..3c422a7 100644 --- a/src/Models/Broadcasts.php +++ b/src/Models/Broadcasts.php @@ -92,7 +92,7 @@ public function broadcastInsert(): PendingBroadcast return $this->broadcastActionTo( $this->broadcastDefaultStreamables(inserting: true), $action, - Rendering::forModel($this), + rendering: Rendering::forModel($this), ); } @@ -126,43 +126,44 @@ public function broadcastRefresh(): PendingBroadcast public function broadcastAppendTo($streamable): PendingBroadcast { - return $this->broadcastActionTo($streamable, 'append', Rendering::forModel($this)); + return $this->broadcastActionTo($streamable, 'append', rendering: Rendering::forModel($this)); } public function broadcastPrependTo($streamable): PendingBroadcast { - return $this->broadcastActionTo($streamable, 'prepend', Rendering::forModel($this)); + return $this->broadcastActionTo($streamable, 'prepend', rendering: Rendering::forModel($this)); } public function broadcastBeforeTo($streamable, string $target): PendingBroadcast { - return $this->broadcastActionTo($streamable, 'before', Rendering::forModel($this), $target); + return $this->broadcastActionTo($streamable, 'before', $target, rendering: Rendering::forModel($this)); } public function broadcastAfterTo($streamable, string $target): PendingBroadcast { - return $this->broadcastActionTo($streamable, 'after', Rendering::forModel($this), $target); + return $this->broadcastActionTo($streamable, 'after', $target, rendering: Rendering::forModel($this)); } public function broadcastReplaceTo($streamable): PendingBroadcast { - return $this->broadcastActionTo($streamable, 'replace', Rendering::forModel($this)); + return $this->broadcastActionTo($streamable, 'replace', rendering: Rendering::forModel($this)); } public function broadcastUpdateTo($streamable): PendingBroadcast { - return $this->broadcastActionTo($streamable, 'update', Rendering::forModel($this)); + return $this->broadcastActionTo($streamable, 'update', rendering: Rendering::forModel($this)); } public function broadcastRemoveTo($streamable): PendingBroadcast { - return $this->broadcastActionTo($streamable, 'remove', Rendering::empty()); + return $this->broadcastActionTo($streamable, 'remove', rendering: Rendering::empty()); } public function broadcastRefreshTo($streamable): PendingBroadcast { - return TurboStream::broadcastRefresh($this->toChannels(Collection::wrap($streamable))) - ->cancelIf(fn () => static::isIgnoringTurboStreamBroadcasts()); + return TurboStream::broadcastRefresh( + $this->toChannels(Collection::wrap($streamable)) + )->cancelIf(fn () => static::isIgnoringTurboStreamBroadcasts()); } public function asTurboStreamBroadcastingChannel() @@ -170,14 +171,15 @@ public function asTurboStreamBroadcastingChannel() return $this->toChannels(Collection::wrap($this->broadcastDefaultStreamables($this->wasRecentlyCreated))); } - protected function broadcastActionTo($streamables, string $action, Rendering $rendering, ?string $target = null): PendingBroadcast + public function broadcastActionTo($streamables, string $action, ?string $target = null, array $attributes = [], ?Rendering $rendering = null): PendingBroadcast { return TurboStream::broadcastAction( action: $action, target: $target ?: $this->broadcastDefaultTarget($action), targets: null, channel: $this->toChannels(Collection::wrap($streamables)), - content: $rendering, + attributes: $attributes, + content: $rendering ?? Rendering::empty(), )->cancelIf(static::isIgnoringTurboStreamBroadcasts()); } diff --git a/tests/Models/BroadcastsModelTest.php b/tests/Models/BroadcastsModelTest.php index 4db0dcf..7c8910d 100644 --- a/tests/Models/BroadcastsModelTest.php +++ b/tests/Models/BroadcastsModelTest.php @@ -718,4 +718,53 @@ public function can_disable_auto_broadcasts() return true; }, times: 1); } + + /** @test */ + public function broadcasts_with_extra_attributes_to_turbo_stream() + { + TurboStream::fake(); + + /** @var Board $board */ + $board = Board::withoutTurboStreamBroadcasts(fn () => Board::create(['name' => 'Hello World'])); + + $board->broadcastActionTo( + $channel = 'messages', + $action = 'test', + attributes: $attributes = ['data-foo' => 'bar'], + ); + + TurboStream::assertBroadcasted(function (PendingBroadcast $turboStream) use ($channel, $action, $attributes) { + $this->assertEquals("private-{$channel}", $turboStream->channels[0]->name); + $this->assertEquals($action, $turboStream->action); + $this->assertEquals($attributes, $turboStream->attributes); + + return true; + }); + } + + /** @test */ + public function broadcasts_with_extra_attributes_to_turbo_stream_with_rendering() + { + TurboStream::fake(); + + /** @var Board $board */ + $board = Board::withoutTurboStreamBroadcasts(fn () => Board::create(['name' => 'Hello World'])); + + $board->broadcastActionTo( + $channel = 'messages', + $action = 'test', + attributes: $attributes = ['data-foo' => 'bar'], + )->view('boards.partials.board', [ + 'board' => $board, + ]); + + TurboStream::assertBroadcasted(function (PendingBroadcast $turboStream) use ($channel, $action, $attributes) { + $this->assertEquals("private-{$channel}", $turboStream->channels[0]->name); + $this->assertEquals($action, $turboStream->action); + $this->assertEquals($attributes, $turboStream->attributes); + $this->assertStringContainsString('Hello World', $turboStream->render()); + + return true; + }); + } } diff --git a/workbench/resources/views/boards/partials/board.blade.php b/workbench/resources/views/boards/partials/board.blade.php new file mode 100644 index 0000000..03b3443 --- /dev/null +++ b/workbench/resources/views/boards/partials/board.blade.php @@ -0,0 +1 @@ +