Framework: Issue with the new x- blade syntax

Created on 9 Mar 2020  路  11Comments  路  Source: laravel/framework

  • Laravel Version: ^7
  • PHP Version: 7.2.12
  • Database Driver & Version:

Description:

I have an issue with the new x- blade syntax.

This is working.
<x-contact-form/>

This is not.
<x-{{ $model->component }}/>

Can I achieve it somehow, to name it dynamically from database?

Steps To Reproduce:

Most helpful comment

Shouldn鈥檛 the old @component syntax still work as well?

My understanding of BladeX and it鈥檚 subsequent implementation in Laravel 7 has been that it works as a preprocessor, but still uses the old component syntax under the hood.

All 11 comments

I guess this is not possible as the template would need to be parsed twice.

You can try this:

1 - Add a sample route

~php
// ./routes/web.php
Route::view('sample', 'sample');
~

2 - Create a base component

~bash
$ php artisan make:component Component
~

3 - Accept the base view as a prop

~~~php
// ./app/View/Components/Component.php

namespace App\View\Components;

// need to rename as our component is named Component
use Illuminate\View\Component as BaseComponent;

class Component extends BaseComponent
{
public $is;

public function __construct($is)
{
    $this->is = $is;
}

public function render()
{
    return "components.{$this->is}";
}

}
~~~

4 - Create the sample blade file (./resources/views.blade.php)

~~~blade

World



There

~~~

5 - Create the expected components files (./resources/components/hello.blade.php)

~~~blade

Hello {{ $slot }}

~~~

and (./resources/components/hi.blade.php)

~~~blade

Hi {{ $slot }}

~~~

6 - Navigate to the /sample route and check the results.


As you can see we don't use the generated component blade files we are determining the template when the component renders, you can remove it (./resources/views/ components/component.balde.php).

The big con is that you might not be able to use class-based components dynamically (at least not with this approach).

The good part is that for simple components you don't need to know beforehand all of them, just add the needed view into the ./resources/views/components directory.


Also, please consider posting this kind of question in one of the support forums:

In general Laravel team advises to use this issue tracker for reporting bugs with the library itself.

Reference: https://github.com/laravel/framework/issues/31729#issuecomment-594578603

I like this approach with all of it's limitations. That's enough for me now. Thank you for your quick answer.

Or maybe this approach (in my case):

@switch($model->component)
    @case('contact-form')
        <x-contact-form />
        @break
    @case('faq')
        <x-faq />
        @break
@endswitch

Or maybe this approach (in my case):

@switch($model->component)
    @case('contact-form')
        <x-contact-form />
        @break
    @case('faq')
        <x-faq />
        @break
@endswitch

I believe this would work but might quickly grow out of scale. I'd opt for the dynamic return value on the Component::render() method.

I've experimented using @switch before writing my answer. The problem I found is forwarding attributes ( style="..."), which worked well with class-less components, but not with class-based components. I don't know if it is intended behavior or something that can be fixed.

Also, as noted by @ryangjchandler , the approach I proposed has the advantage of not needing a long switch block if you have many derived components and reduces maintenance when you need to add new components.

<x-component is="hi" style="color: green">
    There
</x-component>

On second tought it doesn't solve my main problem.

The same issue appears:

<x-component is="{{ $model->component }}" style="color: green">
    There
</x-component>

Dynamic attributes in components have a special syntax:

https://laravel.com/docs/7.x/blade#passing-data-to-components

Try this:

~php

There

~

EDIT updated docs link to correct section

Also, per docs guidelines:

https://laravel.com/docs/7.x/contributions#support-questions

And also shown when you create a new issue, please consider posting this kind of question in one of the support forums:

In general Laravel team advises to use this issue tracker for reporting bugs with the library itself.

Reference: https://github.com/laravel/framework/issues/31729#issuecomment-594578603

Shouldn鈥檛 the old @component syntax still work as well?

My understanding of BladeX and it鈥檚 subsequent implementation in Laravel 7 has been that it works as a preprocessor, but still uses the old component syntax under the hood.

Shouldn鈥檛 the old @component syntax still work as well?

My understanding of BladeX and it鈥檚 subsequent implementation in Laravel 7 has been that it works as a preprocessor, but still uses the old component syntax under the hood.

Correct. The old @component syntax does still work for regular Blade components. The new tag compiler converts the tag into the old style syntax behind the scenes also.

Can find that inside of the ComponentTagCompiler class I believe.

@avanember In that case you should be able to just use:

@component($model->component)
@endcomponent

Unless I misunderstood how the parser works.

The same is likely not possible with the tag component syntax as it relies on a regexp to efficiently match things. (And the idea to use x- as prefix to efficiently find all components is genius)

Was this page helpful?
0 / 5 - 0 ratings