diff --git a/src/Illuminate/View/Compilers/Concerns/CompilesComponents.php b/src/Illuminate/View/Compilers/Concerns/CompilesComponents.php index 7fc998721330..d61dd07726f2 100644 --- a/src/Illuminate/View/Compilers/Concerns/CompilesComponents.php +++ b/src/Illuminate/View/Compilers/Concerns/CompilesComponents.php @@ -3,6 +3,7 @@ namespace Illuminate\View\Compilers\Concerns; use Illuminate\Support\Str; +use Illuminate\View\ComponentAttributeBag; trait CompilesComponents { @@ -167,7 +168,7 @@ protected function compileProps($expression) public static function sanitizeComponentAttribute($value) { return is_string($value) || - (is_object($value) && method_exists($value, '__toString')) + (is_object($value) && ! $value instanceof ComponentAttributeBag && method_exists($value, '__toString')) ? e($value) : $value; } diff --git a/src/Illuminate/View/ComponentAttributeBag.php b/src/Illuminate/View/ComponentAttributeBag.php index d0e2f6545e2b..7cde3735f9cd 100644 --- a/src/Illuminate/View/ComponentAttributeBag.php +++ b/src/Illuminate/View/ComponentAttributeBag.php @@ -141,6 +141,15 @@ public function merge(array $attributeDefaults = []) */ public function setAttributes(array $attributes) { + if (isset($attributes['attributes']) && + $attributes['attributes'] instanceof self) { + $parentBag = $attributes['attributes']; + + unset($attributes['attributes']); + + $attributes = $parentBag->merge($attributes); + } + $this->attributes = $attributes; } diff --git a/tests/View/Blade/BladeComponentTagCompilerTest.php b/tests/View/Blade/BladeComponentTagCompilerTest.php index 0bae5955d88e..f74008ef5ee1 100644 --- a/tests/View/Blade/BladeComponentTagCompilerTest.php +++ b/tests/View/Blade/BladeComponentTagCompilerTest.php @@ -5,7 +5,6 @@ use Illuminate\Container\Container; use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\View\Factory; -use Illuminate\Filesystem\Filesystem; use Illuminate\View\Compilers\BladeCompiler; use Illuminate\View\Compilers\ComponentTagCompiler; use Illuminate\View\Component; diff --git a/tests/View/ViewComponentTest.php b/tests/View/ViewComponentTest.php index 8ceeca0dfc5b..cb33683dfe99 100644 --- a/tests/View/ViewComponentTest.php +++ b/tests/View/ViewComponentTest.php @@ -3,6 +3,7 @@ namespace Illuminate\Tests\View; use Illuminate\View\Component; +use Illuminate\View\ComponentAttributeBag; use PHPUnit\Framework\TestCase; class ViewComponentTest extends TestCase @@ -18,6 +19,15 @@ public function testDataExposure() $this->assertSame('taylor', $variables['hello']('taylor')); } + public function testAttributeParentInheritance() + { + $component = new TestViewComponent; + + $component->withAttributes(['class' => 'foo', 'attributes' => new ComponentAttributeBag(['class' => 'bar', 'type' => 'button'])]); + + $this->assertEquals('class="foo bar" type="button"', (string) $component->attributes); + } + public function testPublicMethodsWithNoArgsAreConvertedToStringableCallablesInvokedAndNotCached() { $component = new TestSampleViewComponent;