PaulH
PaulH

Reputation: 3049

Laravel Invoke or render a component directly from a route or controller

I have a component

class Projects extends Component
{

    public $projects;

    public function __construct()
    {
        $this->projects = Project::get();
    }

    public function render()
    {
        return view('components.projects');
    }
}

and the corresponding components/projects.blade.php file containing

@dump($projects)

I saw somewhere it is possible to return the component view directly from a route. However, none of these works

Route::get('projects1', Projects::class); // error

Route::get('projects2', [Projects::class]); // error

Route::get('projects3', [Projects::class, 'render']); // view does not have access to public $projects

Route::get('projects4', [Projects::class, '__construct']); // renders blank

Route::view('projects5', 'components.projects'); // view does not have access to public $projects

Route::get('projects6', fn() => view('components.projects'));  // view does not have access to public $projects

Route::get('projects7', fn() => <<<'blade'
    <x-projects></x-projects>
blade); // component not accessed

Any clue?

When components/projects.blade.php contains

 @dump(get_defined_vars())

I see

array:5 [▼
  "__path" => "...\storage\framework\views/80c6e39e032dd35edb0d114508f22feaa7951180.php"
  "__data" => array:3 [▶]
  "__env" => Illuminate\View\Factory {#1791 ▶}
  "app" => Illuminate\Foundation\Application {#4 ▶}
  "errors" => Illuminate\Support\ViewErrorBag {#1811 ▶}
]

projects is missing when using

Route::view('projects5', 'components.projects'); 

The component class is not active, only the blade file.

When using either

return view('components.projects');

return (new Projects)->render();

return app(Projects::class)->render();

from a controller, I get the same results.

The only way I can make it act as a component is going via a blade file containing

<x-projects></x-projects>

In that case, I see, as expected for a component:

array:10 [▼
  "__path" => "...\storage\framework\views/80c6e39e032dd35edb0d114508f22feaa7951180.php"
  "__data" => array:8 [▶]
  "__env" => Illuminate\View\Factory {#1793 ▶}
  "app" => Illuminate\Foundation\Application {#4 ▶}
  "errors" => Illuminate\Support\ViewErrorBag {#1813 ▶}
  "projects" => Illuminate\Database\Eloquent\Collection {#1831 ▶}
  "componentName" => "projects"
  "attributes" => Illuminate\View\ComponentAttributeBag {#1820 ▶}
  "slot" => Illuminate\Support\HtmlString {#1823 ▶}
  "__laravel_slots" => array:1 [▶]
]

I wish to avoid to use an intermediate file only referencing the component.

Upvotes: 2

Views: 2301

Answers (1)

PaulH
PaulH

Reputation: 3049

Taylor just showed this new feature at Laracon. It is part of Laravel release 8.83

Route::get('projects', fn() => Blade::renderComponent(new Projects()));

https://youtu.be/0Rq-yHAwYjQ?t=20525

enter image description here

It is this pull request: https://github.com/laravel/framework/pull/40745

Upvotes: 2

Related Questions