Skip to content

Commit c911989

Browse files
authored
fix(view): pass scoped variables down view components (#1467)
1 parent cf504ad commit c911989

File tree

3 files changed

+39
-7
lines changed

3 files changed

+39
-7
lines changed

packages/view/src/Elements/ViewComponentElement.php

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ public function compile(): string
141141
->prepend(
142142
// Open the current scope
143143
sprintf(
144-
'<?php (function ($attributes, $slots %s %s %s) { extract($this->currentView?->data ?? [], EXTR_SKIP); ?>',
144+
'<?php (function ($attributes, $slots, $scopedVariables %s %s) { extract($scopedVariables, EXTR_SKIP); ?>',
145145
$this->dataAttributes->isNotEmpty() ? (', ' . $this->dataAttributes->map(fn (string $_value, string $key) => "\${$key}")->implode(', ')) : '',
146146
$this->expressionAttributes->isNotEmpty() ? (', ' . $this->expressionAttributes->map(fn (string $_value, string $key) => "\${$key}")->implode(', ')) : '',
147147
$this->scopedVariables->isNotEmpty() ? (', ' . $this->scopedVariables->map(fn (string $name) => "\${$name}")->implode(', ')) : '',
@@ -150,18 +150,18 @@ public function compile(): string
150150
->append(
151151
// Close and call the current scope
152152
sprintf(
153-
'<?php })(%s, %s %s %s %s) ?>',
154-
'attributes: ' . ViewObjectExporter::export($this->viewComponentAttributes),
155-
'slots: ' . ViewObjectExporter::export($slots),
153+
'<?php })(attributes: %s, slots: %s, scopedVariables: [%s] + ($scopedVariables ?? $this->currentView?->data ?? []) %s %s) ?>',
154+
ViewObjectExporter::export($this->viewComponentAttributes),
155+
ViewObjectExporter::export($slots),
156+
$this->scopedVariables->isNotEmpty()
157+
? $this->scopedVariables->map(fn (string $name) => "'{$name}' => \${$name}")->implode(', ')
158+
: '',
156159
$this->dataAttributes->isNotEmpty()
157160
? (', ' . $this->dataAttributes->map(fn (mixed $value, string $key) => "{$key}: " . ViewObjectExporter::exportValue($value))->implode(', '))
158161
: '',
159162
$this->expressionAttributes->isNotEmpty()
160163
? (', ' . $this->expressionAttributes->map(fn (mixed $value, string $key) => "{$key}: " . $value)->implode(', '))
161164
: '',
162-
$this->scopedVariables->isNotEmpty()
163-
? (', ' . $this->scopedVariables->map(fn (string $name) => "{$name}: \${$name}")->implode(', '))
164-
: '',
165165
),
166166
);
167167

tests/Integration/Http/GenericResponseSenderTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ public function test_file_response(): void
8282
$response = new File(path: $path);
8383
$responseSender = $this->container->get(GenericResponseSender::class);
8484
$responseSender->send($response);
85+
8586
$content = ob_get_clean();
8687

8788
$this->assertSame(file_get_contents($path), $content);
@@ -94,6 +95,7 @@ public function test_download_response(): void
9495
$response = new Download(path: $path);
9596
$responseSender = $this->container->get(GenericResponseSender::class);
9697
$responseSender->send($response);
98+
9799
$content = ob_get_clean();
98100

99101
$this->assertSame(file_get_contents($path), $content);
@@ -109,6 +111,7 @@ public function test_sending_of_array_to_json(): void
109111

110112
$responseSender = $this->container->get(GenericResponseSender::class);
111113
$responseSender->send($response);
114+
112115
$output = ob_get_clean();
113116

114117
$this->assertSame('{"key":"value"}', $output);
@@ -129,6 +132,7 @@ public function jsonSerialize(): mixed
129132

130133
$responseSender = $this->container->get(GenericResponseSender::class);
131134
$responseSender->send($response);
135+
132136
$output = ob_get_clean();
133137

134138
$this->assertSame('{"key":"value"}', $output);
@@ -145,6 +149,7 @@ public function test_view_body(): void
145149

146150
$responseSender = $this->container->get(GenericResponseSender::class);
147151
$responseSender->send($response);
152+
148153
$output = ob_get_clean();
149154

150155
$this->assertStringContainsString('Hello Brent!', $output);
@@ -156,6 +161,7 @@ public function test_stream(): void
156161
$response = new EventStream(fn () => yield 'hello');
157162
$responseSender = $this->container->get(GenericResponseSender::class);
158163
$responseSender->send($response);
164+
159165
$output = ob_get_clean();
160166
ob_start();
161167

@@ -172,6 +178,7 @@ public function test_stream_with_custom_event(): void
172178
});
173179
$responseSender = $this->container->get(GenericResponseSender::class);
174180
$responseSender->send($response);
181+
175182
$output = ob_get_clean();
176183
ob_start();
177184

@@ -190,6 +197,7 @@ public function test_stream_with_custom_id(): void
190197
});
191198
$responseSender = $this->container->get(GenericResponseSender::class);
192199
$responseSender->send($response);
200+
193201
$output = ob_get_clean();
194202
ob_start();
195203

@@ -208,6 +216,7 @@ public function test_stream_with_custom_retry(): void
208216
});
209217
$responseSender = $this->container->get(GenericResponseSender::class);
210218
$responseSender->send($response);
219+
211220
$output = ob_get_clean();
212221
ob_start();
213222

@@ -223,13 +232,17 @@ public function test_stream_with_custom_implementation(): void
223232
$response = new EventStream(function () {
224233
yield new class implements ServerSentEvent {
225234
public ?int $id = 1;
235+
226236
public null|Duration|int $retryAfter = null;
237+
227238
public ?string $event = 'custom';
239+
228240
public JsonSerializable|Stringable|string|iterable $data = ['foo', 'bar'];
229241
};
230242
});
231243
$responseSender = $this->container->get(GenericResponseSender::class);
232244
$responseSender->send($response);
245+
233246
$output = ob_get_clean();
234247
ob_start();
235248

tests/Integration/View/ViewComponentTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -960,4 +960,23 @@ public function test_view_variables_are_passed_into_the_component(): void
960960

961961
$this->assertSnippetsMatch('test', $html);
962962
}
963+
964+
public function test_capture_outer_scope_view_component_variables(): void
965+
{
966+
$this->registerViewComponent('x-a', '<x-slot />');
967+
$this->registerViewComponent('x-b', '<x-slot />');
968+
969+
$html = $this->render(
970+
<<<'HTML'
971+
<x-a :foreach="$items as $item">
972+
<x-b>
973+
{{ $item }}
974+
</x-b>
975+
</x-a>
976+
HTML,
977+
items: ['a', 'b'],
978+
);
979+
980+
$this->assertSnippetsMatch('a b', $html);
981+
}
963982
}

0 commit comments

Comments
 (0)