Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
calebporzio committed Jun 12, 2023
1 parent 4f00666 commit b58fccd
Show file tree
Hide file tree
Showing 17 changed files with 436 additions and 199 deletions.
30 changes: 16 additions & 14 deletions docs/dirty.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@

In a traditional HTML form setup, the form is only ever submitted when the user presses the "Submit" button.
In a traditional HTML page containing a form, the form is only ever submitted when the user presses the "Submit" button.

However, Livewire is capable of much more than a traditional form submission. You can validate form inputs in real-time, or save the form as a user types.
However, Livewire is capable of much more than a traditional form submission. You can validate form inputs in real-time or save the form as a user types.

In these "real-time" update scenarios, is can be helpful to signal to your users when a form or subset of a form has been changed, but hasn't been saved to the database.
In these "real-time" update scenarios, it can be helpful to signal to your users when a form or subset of a form has been changed but hasn't been saved to the database.

When a form contains un-saved input, that form is considered "dirty". It only becomes "clean", when a network request has been triggered to synchronize the server state with the client-side state.
When a form contains un-saved input, that form is considered "dirty". It only becomes "clean" when a network request has been triggered to synchronize the server state with the client-side state.

## Basic usage

Livewire allows you to easily toggle visual elements on the page using the `wire:dirty` syntax.

By adding `wire:dirty` to an element, you are telling Livewire to hide it anytime the client-side state is in-sync with the server-side state.
By adding `wire:dirty` to an element, you are telling Livewire to only show it when the client-side state diverges from the server-side state.

To demonstrate, below is an example of an `UpdatePost` form containing an "Unsaved changes..." visual indication that signals to the user that the form contains input that is "un-saved":
To demonstrate, here is an example of an `UpdatePost` form containing an "Unsaved changes..." visual indication that signals to the user that the form contains input that is "un-saved":

```html
<form wire:submit="update">
<input type="text" wire:model="title">

<!-- ... -->

<button type="submit">Update</button>

<div wire:dirty>Unsaved changes...</div>
<div wire:dirty>Unsaved changes...</div> <!-- [tl! highlight] -->
</form>
```

Because `wire:dirty` has been added to the "Unsaved changes..." message, initially the message will not show up, but as soon as a user starts modifying form inputs, it will show up.
Because `wire:dirty` has been added to the "Unsaved changes..." message, initially, the message will not show up, but as soon as a user starts modifying form inputs, it will show up.

When the form is submitted by the user, the message will dissapear as the server/client data is back in-sync.
When the user submits the form, the message will dissapear as the server/client data is back in sync.

### Removing elements

Expand All @@ -39,25 +41,25 @@ By adding `.remove`, you can instead show an element by default and only hide it

## Targeting property updates

If you are using `wire:model.lazy` to update a property on the server after a user leaves the input field, you can provide a "dirty" indication for that specific property by adding `wire:target` to the element.
Suppose you are using `wire:model.blur` to update a property on the server after a user leaves the input field. In that case, you can provide a "dirty" indication for that property by adding `wire:target` to the element.

Here is an example of only showing a dirty indication when the title property has been changed

```html
<form wire:submit="update">
<input wire:model.lazy="title">
<input wire:model.blur="title">

<div wire:dirty wire:target="title">Unsaved title...</div>
<div wire:dirty wire:target="title">Unsaved title...</div> <!-- [tl! highlight] -->

<button type="submit">Update</button>
</form>
```

## Toggling classes

Often, instead of toggling entire elements, you may want to toggle individual CSS classes on an input when it's state is "dirty".
Often, instead of toggling entire elements, you may want to toggle individual CSS classes on an input when its state is "dirty".

Here's an example where as a user types into an input field, the border becomes yellow, indicating an "unsaved" state, then when the user tabs away from the field, the border is removed, indicating that the state has been saved on the server:
Here's an example where a user types into an input field and the border becomes yellow, indicating an "unsaved" state, then when the user tabs away from the field, the border is removed, indicating that the state has been saved on the server:

```html
<input wire:model.lazy="title" wire:dirty.class="border-yellow-500">
Expand Down
6 changes: 3 additions & 3 deletions docs/downloads.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

File downloads in Livewire work much the same as in Laravel itself. For the most part, you can use any Laravel download utility inside a Livewire component and it should work as expected.
File downloads in Livewire work much the same as in Laravel itself. For the most part, you can use any Laravel download utility inside a Livewire component, and it should work as expected.

It's worth noting however, that under the hood, file downloads are handled differently than in a standard Laravel application. In Livewire, the file's contents are base 64 encoded, sent to the frontend, and decoded back into binary to be downloaded directly from the client.
It's worth noting, however, that under the hood, file downloads are handled differently than in a standard Laravel application. In Livewire, the file's contents are base 64 encoded, sent to the frontend, and decoded back into binary to be downloaded directly from the client.

## Basic usage

Expand Down Expand Up @@ -62,7 +62,7 @@ public function download()

## Streaming downloads

Livewire can also stream downloads, however, they aren't truly streamed. The download isn't triggered until the entirety of its contents are collected and delivered to the content.
Livewire can also stream downloads; however, they aren't truly streamed. The download isn't triggered until its contents are collected and delivered to the browser.

```php
public function download()
Expand Down
99 changes: 82 additions & 17 deletions docs/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,8 @@ class OrderShipped implements ShouldBroadcast
{
use InteractsWithSockets, SerializesModels;

public Order $order;

public function broadcastOn()
{
return new Channel('orders');
Expand All @@ -287,15 +289,15 @@ OrderShipped::dispatch();
If you were to listen for this event in JavaScript using only Laravel Echo, it would look something like this:

```js
Echo.private('orders')
.listen('OrderShipmentStatusUpdated', e => {
Echo.channel('orders')
.listen('OrderShipped', e => {
console.log(e.order)
})
```

Assuming you have Laravel Echo installed and configured, you can listen for this event from inside a Livewire component.

Below is an example of a component called `OrderTracker` that is listening for the `OrderShipped` event and to show users a visual indication of a new order:
Below is an example of a component called `OrderTracker` that is listening for the `OrderShipped` event to show users a visual indication of a new order:

```php
<?php
Expand All @@ -309,30 +311,93 @@ class OrderTracker extends Component
{
public $showNewOrderNotification = false;

// @todo - left off here
protected function mount() {
$this->js(<<<JS
Echo.listen('orders')
.presence()
JS);
#[On('echo:orders,OrderShipped')]
public function notifyNewOrder()
{
$this->showNewOrderNotification = true;
}

protected function echo() {
// ...
}
```

If you have Echo channels with variables embedded in it (such as a Order ID) you can use the `getListeners()` function instead of the `#[On]` attribute:

```php
<?php

namespace App\Http\Livewire;

use Livewire\Attributes\Prop;
use Livewire\Attributes\On;
use Livewire\Component;
use App\Models\Order;

class OrderTracker extends Component
{
#[Prop]
public Order $order;

public $showOrderShippedNotification = false;

public function getListeners()
{
return [
'notifyNewOrder' => new Echo(
private: true,
channel: 'orders',
event: '',
),
"echo:orders.{$this->order->id},OrderShipped" => 'notifyShipped',
];
}

public function notifyNewOrder()
#[On('echo:orders,OrderShipped')]
public function notifyShipped()
{
$this->showNewOrderNotification = true;
$this->showOrderShippedNotification = true;
}

// ...
}
```

Now, Livewire will intercept the received event from Echo, and act accordingly.

### Private & presence channels

In a similar way to regular public channels, you can also listen to events broadcasted to private and presence channels:

> [!info]
> Make sure you have your <a href="https://laravel.com/docs/master/broadcasting#defining-authorization-callbacks">Authentication Callbacks</a> properly defined.
```php
<?php

namespace App\Http\Livewire;

use Livewire\Attributes\On;
use Livewire\Component;

class OrderTracker extends Component
{
public $showNewOrderNotification = false;

public function getListeners()
{
return [
// Public Channel
"echo:orders,OrderShipped" => 'notifyNewOrder',

// Private Channel
"echo-private:orders,OrderShipped" => 'notifyNewOrder',

// Presence Channel
"echo-presence:orders,OrderShipped" => 'notifyNewOrder',
"echo-presence:orders,here" => 'notifyNewOrder',
"echo-presence:orders,joining" => 'notifyNewOrder',
"echo-presence:orders,leaving" => 'notifyNewOrder',
];
}

public function notifyNewOrder()
{
$this->showNewOrderNotification = true;
}
}
```
5 changes: 3 additions & 2 deletions docs/extending.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
## Registering components manually
Coming soon...

## Synthesizers
<!-- @todo -->
j
Loading

0 comments on commit b58fccd

Please sign in to comment.