Skip to content

Commit

Permalink
Name attributes on slots (#47065)
Browse files Browse the repository at this point in the history
* support name attributes on slots if using inline syntax

* add file

* formatting and another test

* simplify conditions
  • Loading branch information
taylorotwell authored May 12, 2023
1 parent a38ae49 commit a7f454c
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 3 deletions.
15 changes: 12 additions & 3 deletions src/Illuminate/View/Compilers/ComponentTagCompiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,8 @@ public function compileSlots(string $value)
\s*
x[\-\:]slot
(?:\:(?<inlineName>\w+(?:-\w+)*))?
(?:\s+(:?)name=(?<name>(\"[^\"]+\"|\\\'[^\\\']+\\\'|[^\s>]+)))?
(?:\s+name=(?<name>(\"[^\"]+\"|\\\'[^\\\']+\\\'|[^\s>]+)))?
(?:\s+\:name=(?<boundName>(\"[^\"]+\"|\\\'[^\\\']+\\\'|[^\s>]+)))?
(?<attributes>
(?:
\s+
Expand Down Expand Up @@ -544,20 +545,28 @@ public function compileSlots(string $value)
/x";

$value = preg_replace_callback($pattern, function ($matches) {
$name = $this->stripQuotes($matches['inlineName'] ?: $matches['name']);
$name = $this->stripQuotes($matches['inlineName'] ?: $matches['name'] ?: $matches['boundName']);

if (Str::contains($name, '-') && ! empty($matches['inlineName'])) {
$name = Str::camel($name);
}

if ($matches[2] !== ':') {
// If the name was given as a simple string, we will wrap it in quotes as if it was bound for convenience...
if (! empty($matches['inlineName']) || ! empty($matches['name'])) {
$name = "'{$name}'";
}

$this->boundAttributes = [];

$attributes = $this->getAttributesFromAttributeString($matches['attributes']);

// If an inline name was provided and a name or bound name was *also* provided, we will assume the name should be an attribute...
if (! empty($matches['inlineName']) && (! empty($matches['name']) || ! empty($matches['boundName']))) {
$attributes = ! empty($matches['name'])
? array_merge($attributes, $this->getAttributesFromAttributeString('name='.$matches['name']))
: array_merge($attributes, $this->getAttributesFromAttributeString(':name='.$matches['boundName']));
}

return " @slot({$name}, null, [".$this->attributesToString($attributes).']) ';
}, $value);

Expand Down
44 changes: 44 additions & 0 deletions tests/Integration/View/BladeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,50 @@ public function test_consume_with_props()
<div>Slot: F, Color: yellow, Default: foo</div>', trim($view));
}

public function test_name_attribute_can_be_used_if_using_short_slot_names()
{
$content = Blade::render('<x-input-with-slot>
<x-slot:input name="my_form_field" class="text-input-lg" data-test="data">Test</x-slot:input>
</x-input-with-slot>');

$this->assertSame('<div>
<input type="text" class="input text-input-lg" data-test="data" name="my_form_field" />
</div>', trim($content));
}

public function test_name_attribute_cant_be_used_if_not_using_short_slot_names()
{
$content = Blade::render('<x-input-with-slot>
<x-slot name="input" class="text-input-lg" data-test="data">Test</x-slot>
</x-input-with-slot>');

$this->assertSame('<div>
<input type="text" class="input text-input-lg" data-test="data" />
</div>', trim($content));
}

public function test_bound_name_attribute_can_be_used_if_using_short_slot_names()
{
$content = Blade::render('<x-input-with-slot>
<x-slot:input :name="\'my_form_field\'" class="text-input-lg" data-test="data">Test</x-slot:input>
</x-input-with-slot>');

$this->assertSame('<div>
<input type="text" class="input text-input-lg" data-test="data" name="my_form_field" />
</div>', trim($content));
}

public function test_bound_name_attribute_can_be_used_if_using_short_slot_names_and_not_first_attribute()
{
$content = Blade::render('<x-input-with-slot>
<x-slot:input class="text-input-lg" :name="\'my_form_field\'" data-test="data">Test</x-slot:input>
</x-input-with-slot>');

$this->assertSame('<div>
<input type="text" class="input text-input-lg" name="my_form_field" data-test="data" />
</div>', trim($content));
}

protected function getEnvironmentSetUp($app)
{
$app['config']->set('view.paths', [__DIR__.'/templates']);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@props([
'input'
])

<div>
<input type="text" {{ $input->attributes->class('input') }} />
</div>

0 comments on commit a7f454c

Please sign in to comment.