``` Now, you can import `Alpine` and `Livewire` into your application's bundle like so: ```js import { Livewire, Alpine } from '../../vendor/livewire/livewire/dist/livewire.esm'; import customPlugin from './plugins/custom-plugin' Alpine.plugin(customPlugin) Livewire.start() ``` Notice you no longer need to call `Alpine.start()`. Livewire will start Alpine automatically. For more information, please consult our documentation on [manually bundling Livewire's JavaScript](/docs/installation#manually-bundling-livewire-and-alpine). ## `wire:model` In Livewire 3, `wire:model` is "deferred" by default (instead of by `wire:model.defer`). To achieve the same behavior as `wire:model` from Livewire 2, you must use `wire:model.live`. Below is a list of the necessary substitutions you will need to make in your templates to keep your application's behavior consistent: ```html ``` ## `@entangle` Similar to the changes to `wire:model`, Livewire 3 defers all data binding by default. To match this behavior, `@entangle` has been updated as well. To keep your application running as expected, make the following `@entangle` substitutions: ```blade @entangle(...) @entangle(...).live @entangle(...).defer @entangle(...) ``` ## Events In Livewire 2, Livewire had two different PHP methods for triggering events: * `emit()` * `dispatchBrowserEvent()` Livewire 3 has unified these two methods into a single method: * `dispatch()` Here is a basic example of dispatching and listening for an event in Livewire 3: ```php // Dispatching... class CreatePost extends Component { public Post $post; public function save() { $this->dispatch('post-created', postId: $this->post->id); } } // Listening... class Dashboard extends Component { #[On('post-created')] public function postAdded($postId) { // } } ``` The three main changes from Livewire 2 are: 1. `emit()` has been renamed to `dispatch()` 1. `dispatchBrowserEvent()` has been renamed to `dispatch()` 2. All event parameters must be named For more information, check out the new [events documentation page](/docs/events). Here are the "find and replace" differences that should be applied to your application: ```php $this->emit('post-created'); // [tl! remove] $this->dispatch('post-created'); // [tl! add] $this->emitTo('foo', 'post-created'); // [tl! remove] $this->dispatch('post-created')->to('foo'); // [tl! add] $this->emitSelf('post-created'); // [tl! remove] $this->dispatch('post-created')->self(); // [tl! add] $this->emit('post-created', $post->id); // [tl! remove] $this->dispatch('post-created', postId: $post->id); // [tl! add] $this->dispatchBrowserEvent('post-created'); // [tl! remove] $this->dispatch('post-created'); // [tl! add] $this->dispatchBrowserEvent('post-created', ['postId' => $post->id]); // [tl! remove] $this->dispatch('post-created', postId: $post->id); // [tl! add] ``` ```html ``` ### `emitUp()` The concept of `emitUp` has been removed entirely. Events are now dispatched using browser events and therefore will "bubble up" by default. You can remove any instances of `$this->emitUp(...)` or `$emitUp(...)` from your components. ### Testing events Livewire has also changed event assertions to match the new unified terminology regarding dispatching events: ```php Livewire::test(Component::class)->assertEmitted('post-created'); // [tl! remove] Livewire::test(Component::class)->assertDispatched('post-created'); // [tl! add] Livewire::test(Component::class)->assertEmittedTo(Foo::class, 'post-created'); // [tl! remove] Livewire::test(Component::class)->assertDispatchedTo(Foo:class, 'post-created'); // [tl! add] Livewire::test(Component::class)->assertNotEmitted('post-created'); // [tl! remove] Livewire::test(Component::class)->assertNotDispatched('post-created'); // [tl! add] Livewire::test(Component::class)->assertEmittedUp() // [tl! remove] ``` ### URL query string In previous Livewire versions, if you bound a property to the URL's query string, the property value would always be present in the query string, unless you used the `except` option. In Livewire 3, all properties bound to the query string will only show up if their value has been changed after the page load. This default removes the need for the `except` option: ```php public $search = ''; protected $queryString = [ 'search' => ['except' => ''], // [tl! remove] 'search', // [tl! add] ]; ``` If you'd like to revert back to the Livewire 2 behavior of always showing a property in the query string no matter its value, you can use the `keep` option: ```php public $search = ''; protected $queryString = [ 'search' => ['keep' => true], // [tl! highlight] ]; ``` ## Pagination The pagination system has been updated in Livewire 3 to better support multiple paginators within the same component. ### Update published pagination views If you've published Livewire's pagination views, you can reference the new ones in the [pagination directory on GitHub](https://github.com/livewire/livewire/tree/master/src/Features/SupportPagination/views) and update your application accordingly. ### Accessing `$this->page` directly Because Livewire now supports multiple paginators per component, it has removed the `$page` property from the component class and replaced it with a `$paginators` property that stores an array of paginators: ```php $this->page = 2; // [tl! remove] $this->paginators['page'] = 2; // [tl! add] ``` However, it is recommended that you use the provided `getPage` and `setPage` methods to modify and access the current page: ```php // Getter... $this->getPage(); // Setter... $this->setPage(2); ``` ### `wire:click.prefetch` Livewire's prefetching feature (`wire:click.prefetch`) has been removed entirely. If you depended on this feature, your application will still work, it will just be slightly less performant in the instances where you were previously benefiting from `.prefetch`. ```html