Skip to content

Commit 7922d93

Browse files
Merge branch 'giusepetroso-feat/inertia-defer-groups'
2 parents 4a420fb + 9abd930 commit 7922d93

File tree

5 files changed

+105
-15
lines changed

5 files changed

+105
-15
lines changed

docs/advanced-usage/use-with-inertia.md

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ title: Use with Inertia
33
weight: 9
44
---
55

6-
> Inertia.js lets you quickly build modern single-page React, Vue, and Svelte apps using classic server-side routing and controllers.
6+
> Inertia.js lets you quickly build modern single-page React, Vue, and Svelte apps using classic server-side routing and
7+
> controllers.
78
89
Laravel Data works excellent with [Inertia](https://inertiajs.com).
910

@@ -15,10 +16,13 @@ return Inertia::render('Song', SongsData::from($song));
1516

1617
## Lazy properties
1718

18-
This package supports [lazy](https://spatie.be/docs/laravel-data/v4/as-a-resource/lazy-properties) properties, which can be manually included or excluded.
19+
This package supports [lazy](https://spatie.be/docs/laravel-data/v4/as-a-resource/lazy-properties) properties, which can
20+
be manually included or excluded.
1921

20-
Inertia has a similar concept called [lazy data evaluation](https://inertiajs.com/partial-reloads#lazy-data-evaluation), where some properties wrapped in a closure only get evaluated and included in the response when explicitly asked.
21-
Inertia v2 introduced the concept of [deferred props](https://inertiajs.com/deferred-props), which allows to defer the loading of certain data until after the initial page render.
22+
Inertia has a similar concept called [lazy data evaluation](https://inertiajs.com/partial-reloads#lazy-data-evaluation),
23+
where some properties wrapped in a closure only get evaluated and included in the response when explicitly asked.
24+
Inertia v2 introduced the concept of [deferred props](https://inertiajs.com/deferred-props), which allows to defer the
25+
loading of certain data until after the initial page render.
2226

2327
This package can output specific properties as Inertia lazy or deferred props as such:
2428

@@ -57,9 +61,36 @@ router.reload((url, {
5761
});
5862
```
5963
64+
#### Deferred property groups
65+
66+
It is possible to group deferred properties together, so that all grouped properties are loaded at the same time. In
67+
order to achieve this, you can pass a group name as the second argument to `Lazy::inertiaDeferred()`:
68+
69+
```php
70+
class SongData extends Data
71+
{
72+
public function __construct(
73+
public Lazy|string $title,
74+
public Lazy|string $artist,
75+
public Lazy|string $lyrics,
76+
) {
77+
}
78+
79+
public static function fromModel(Song $song): self
80+
{
81+
return new self(
82+
Lazy::inertiaDeferred(fn() => $song->title),
83+
Lazy::inertiaDeferred(fn() => $song->artist, 'details')
84+
Lazy::inertiaDeferred(fn() => $song->lyrics, 'details')
85+
);
86+
}
87+
}
88+
```
89+
6090
### Auto lazy Inertia properties
6191
62-
We already saw earlier that the package can automatically make properties Lazy, the same can be done for Inertia properties.
92+
We already saw earlier that the package can automatically make properties Lazy, the same can be done for Inertia
93+
properties.
6394
6495
It is possible to rewrite the previous example as follows:
6596
@@ -82,7 +113,8 @@ class SongData extends Data
82113
}
83114
```
84115
85-
If all the properties of a class should be either Inertia or closure lazy, you can use the attributes on the class level:
116+
If all the properties of a class should be either Inertia or closure lazy, you can use the attributes on the class
117+
level:
86118
87119
```php
88120
#[AutoInertiaLazy]
@@ -95,3 +127,23 @@ class SongData extends Data
95127
}
96128
}
97129
```
130+
131+
#### Deferred property groups
132+
133+
For the `AutoInertiaDeferred` attribute, it is also possible to specify a group name in order to group deferred
134+
properties together:
135+
136+
```php
137+
class SongData extends Data
138+
{
139+
public function __construct(
140+
#[AutoInertiaDeferred()]
141+
public Lazy|string $title,
142+
#[AutoInertiaDeferred('details')]
143+
public Lazy|string $artist,
144+
#[AutoInertiaDeferred('details')]
145+
public Lazy|string $lyrics,
146+
) {
147+
}
148+
}
149+
```

src/Attributes/AutoInertiaDeferred.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,13 @@
1111
#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_PROPERTY)]
1212
class AutoInertiaDeferred extends AutoLazy
1313
{
14+
public function __construct(
15+
protected ?string $group = null,
16+
) {
17+
}
18+
1419
public function build(Closure $castValue, mixed $payload, DataProperty $property, mixed $value): InertiaDeferred
1520
{
16-
return Lazy::inertiaDeferred(fn () => $castValue($value));
21+
return Lazy::inertiaDeferred(fn () => $castValue($value), $this->group);
1722
}
1823
}

src/Lazy.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ public static function inertia(Closure $value): InertiaLazy
3838
return new InertiaLazy($value);
3939
}
4040

41-
public static function inertiaDeferred(mixed $value): InertiaDeferred
41+
public static function inertiaDeferred(mixed $value, ?string $group = null): InertiaDeferred
4242
{
43-
return new InertiaDeferred($value);
43+
return new InertiaDeferred($value, $group);
4444
}
4545

4646
public static function closure(Closure $closure): ClosureLazy

src/Support/Lazy/InertiaDeferred.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66

77
class InertiaDeferred extends ConditionalLazy
88
{
9+
private ?string $group;
10+
911
public function __construct(
1012
mixed $value,
13+
?string $group = null,
1114
) {
1215
$callback = match (true) {
1316
$value instanceof DeferProp => fn () => $value(),
@@ -16,10 +19,14 @@ public function __construct(
1619
};
1720

1821
parent::__construct(fn () => true, $callback);
22+
23+
$this->group = $value instanceof DeferProp && $value->group() !== 'default'
24+
? $value->group()
25+
: $group;
1926
}
2027

2128
public function resolve(): DeferProp
2229
{
23-
return new DeferProp($this->value);
30+
return new DeferProp($this->value, $this->group);
2431
}
2532
}

tests/CreationTest.php

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,75 +1498,104 @@ public function __construct(
14981498
->each()->toBeInstanceOf(FakeNestedModelData::class);
14991499
});
15001500

1501-
15021501
it('can create a data object with inertia deferred properties', function () {
15031502
$dataClass = new class () extends Data {
15041503
public InertiaDeferred|string $deferred;
15051504

1505+
public InertiaDeferred|string $deferredWithGroup;
1506+
15061507
public function __construct()
15071508
{
15081509
}
15091510
};
15101511

15111512
$data = $dataClass::from([
15121513
"deferred" => Lazy::inertiaDeferred(Inertia::defer(fn () => 'Deferred Value')),
1514+
"deferredWithGroup" => Lazy::inertiaDeferred(Inertia::defer(fn () => 'Deferred Value', 'deferred-group')),
15131515
]);
15141516

15151517
expect($data->deferred)->toBeInstanceOf(InertiaDeferred::class);
15161518
expect($data->all()['deferred'])->toBeInstanceOf(DeferProp::class);
15171519
expect($data->all()['deferred']())->toBe('Deferred Value');
15181520

1521+
expect($data->deferredWithGroup)->toBeInstanceOf(InertiaDeferred::class);
1522+
expect($data->all()['deferredWithGroup'])->toBeInstanceOf(DeferProp::class);
1523+
expect($data->all()['deferredWithGroup']())->toBe('Deferred Value');
1524+
expect($data->all()['deferredWithGroup']->group())->toBe('deferred-group');
15191525
});
15201526

15211527
it('can create a data object with inertia deferred closure', function () {
15221528
$dataClass = new class () extends Data {
15231529
public InertiaDeferred|string $deferred;
15241530

1531+
public InertiaDeferred|string $deferredWithGroup;
1532+
15251533
public function __construct()
15261534
{
15271535
}
15281536
};
15291537

15301538
$data = $dataClass::from([
15311539
"deferred" => Lazy::inertiaDeferred(fn () => 'Deferred Value'),
1540+
"deferredWithGroup" => Lazy::inertiaDeferred(fn () => 'Deferred Value', 'deferred-group'),
15321541
]);
15331542

15341543
expect($data->deferred)->toBeInstanceOf(InertiaDeferred::class);
15351544
expect($data->all()['deferred'])->toBeInstanceOf(DeferProp::class);
15361545
expect($data->all()['deferred']())->toBe('Deferred Value');
15371546

1547+
expect($data->deferredWithGroup)->toBeInstanceOf(InertiaDeferred::class);
1548+
expect($data->all()['deferredWithGroup'])->toBeInstanceOf(DeferProp::class);
1549+
expect($data->all()['deferredWithGroup']())->toBe('Deferred Value');
1550+
expect($data->all()['deferredWithGroup']->group())->toBe('deferred-group');
1551+
15381552
});
15391553

15401554
it('can create a data object with inertia deferred value', function () {
15411555
$dataClass = new class () extends Data {
15421556
public InertiaDeferred|string $deferred;
15431557

1558+
public InertiaDeferred|string $deferredWithGroup;
1559+
15441560
public function __construct()
15451561
{
15461562
}
15471563
};
15481564

15491565
$data = $dataClass::from([
15501566
"deferred" => Lazy::inertiaDeferred('Deferred Value'),
1567+
"deferredWithGroup" => Lazy::inertiaDeferred('Deferred Value', 'deferred-group'),
15511568
]);
15521569

15531570
expect($data->deferred)->toBeInstanceOf(InertiaDeferred::class);
15541571
expect($data->all()['deferred'])->toBeInstanceOf(DeferProp::class);
15551572
expect($data->all()['deferred']())->toBe('Deferred Value');
15561573

1574+
expect($data->deferredWithGroup)->toBeInstanceOf(InertiaDeferred::class);
1575+
expect($data->all()['deferredWithGroup'])->toBeInstanceOf(DeferProp::class);
1576+
expect($data->all()['deferredWithGroup']())->toBe('Deferred Value');
1577+
expect($data->all()['deferredWithGroup']->group())->toBe('deferred-group');
15571578
});
15581579

15591580
it('can use auto deferred to construct a inertia deferred property', function () {
15601581
$dataClass = new class () extends Data {
15611582
#[AutoInertiaDeferred]
15621583
public InertiaDeferred|string $string;
1584+
1585+
#[AutoInertiaDeferred('deferred-group')]
1586+
public InertiaDeferred|string $deferredWithGroup;
15631587
};
15641588

1565-
$data = $dataClass::from(['string' => 'Deferred Value']);
1589+
$data = $dataClass::from(['string' => 'Deferred Value', 'deferredWithGroup' => 'Deferred Value']);
15661590

15671591
expect($data->string)->toBeInstanceOf(InertiaDeferred::class);
15681592
expect($data->all()['string'])->toBeInstanceOf(DeferProp::class);
15691593
expect($data->all()['string']())->toBe('Deferred Value');
1594+
1595+
expect($data->deferredWithGroup)->toBeInstanceOf(InertiaDeferred::class);
1596+
expect($data->all()['deferredWithGroup'])->toBeInstanceOf(DeferProp::class);
1597+
expect($data->all()['deferredWithGroup']())->toBe('Deferred Value');
1598+
expect($data->all()['deferredWithGroup']->group())->toBe('deferred-group');
15701599
});
15711600

15721601
it('can use class level auto deferred to construct a inertia deferred property', function () {
@@ -1576,16 +1605,13 @@ class AutoDeferredData extends Data
15761605
public InertiaDeferred|string $string;
15771606
}
15781607

1579-
;
1580-
15811608
$data = AutoDeferredData::from(['string' => 'Deferred Value']);
15821609

15831610
expect($data->string)->toBeInstanceOf(InertiaDeferred::class);
15841611
expect($data->all()['string'])->toBeInstanceOf(DeferProp::class);
15851612
expect($data->all()['string']())->toBe('Deferred Value');
15861613
});
15871614

1588-
15891615
describe('property-morphable creation tests', function () {
15901616
enum TestPropertyMorphableEnum: string
15911617
{

0 commit comments

Comments
 (0)