Framework: Attributes not specified in component constructor are not available inside the class

Created on 22 Apr 2020  路  10Comments  路  Source: laravel/framework


  • Laravel Version: 7.7.1
  • PHP Version: 7.4.3
  • Database Driver & Version: Not applicable

Description:

Currently, if you create a class based Blade component and pass it attributes, only attributes specified in the class constructor are available from the class itself, and the rest only from the template via the $attributes bag. I would imagine that them being available at some point in the component's class would be the expected behavior.

Steps To Reproduce:

Create a class component.

<div {{ $attributes }}>
    ...
</div>
class TestSubject extends Component
{
    public function __construct()
    {
        dump($this->attributes); // produces null, should be ['test1' => 'asd', 'test2' => 'asdads' ...]
    }

    public function render()
    {
        dump($this->attributes); // still null
        return $this->view('components.test-subject');
    }
}

Attempt to insert it with any number of attributes:

<x-test-subject :test1="'asd'" test2="asdads" test3="asdads" />

Most helpful comment

Attributes and slots should be available inside the component class.

All 10 comments

Seems like that's how it is designed. If you pass something in, you must accept it. Same thing with vue. Passed props must be declared or they're not accessible.

@devcircus Vue components have access to all attributes not specifically declared as props via this.$attr property. I'm looking for similar behavior here.

True, but I would still say that, as this was how the components were designed, accessing implicitly received attributes would be a feature request and not a bug report. Probably best to open an issue on the ideas repo and see what the community thinks, or try a PR.

I've created a small PR to fix this issue: #32505

This isn't a bug so closing this. Let's see how the pr goes.

Attributes and slots should be available inside the component class.

@samlovescoding you can in a more recent Laravel version. If you return a closure from a component you'll get an array with:

  1. Component name
  2. Attributes
  3. Slot

I'll send in a PR to document this.

    public function render()
    {
        return function (array $data) {
            return view('components.foo');
        };
    }

@samlovescoding you can in a more recent Laravel version. If you return a closure from a component you'll get an array with:

  1. Component name
  2. Attributes
  3. Slot

I'll send in a PR to document this.

    public function render()
    {
        return function (array $data) {
            return view('components.foo');
        };
    }

I get an exception in simply returning view('components.foo'). Passing the $data and chaining the render() method to get the view contents worked for me.

public function render()
{
    return function (array $data) {
        return view('components.foo', $data)->render();
    };
}

@earvinpiamonte docs have been updated for that in the meantime already.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

PhiloNL picture PhiloNL  路  3Comments

jackmu95 picture jackmu95  路  3Comments

kerbylav picture kerbylav  路  3Comments

felixsanz picture felixsanz  路  3Comments

RomainSauvaire picture RomainSauvaire  路  3Comments