pieterdejong's avatar

Load blade components from a package

I'm trying to create a package where i can put all my blade components. So i can include my repo in all my future applications, and the only thing i have to do is update this single package instead of copy paste all new code to all my applications.

At this point, the component class is being loaded but the template is not found. I ran out of ideas how to load my blade templates. This is my setup.

O, and i don't want to publish the templates, because that would mean i should run an extra command for each application i want to update.

I hope someone can see thru my stupidity and point out what i'm doing wrong. Thanks in advance

Textarea Component

<?php

namespace PHPieter\LB4C\View\Components\Form;

use Illuminate\View\Component;

class Textarea extends Component
{
    public ?string $name;

    public function __construct(?string $name = null)
    {
        $this->name = $name;
    }

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

PackageServiceProvider

<?php

namespace PHPieter\LB4C;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
use PHPieter\LB4C\View\Components\Form\Textarea;


class LibraryServiceProvider extends ServiceProvider
{
    /** @var string */
    private const CONFIG_FILE = __DIR__ . '/../config/library.php';

    /** @var string */
    private const PATH_VIEWS = __DIR__ . '../resources/views/';

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register(): void
    {
        $this->mergeConfigFrom(self::CONFIG_FILE, 'library');
    }


    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot(): void
    {
        $this->loadViewsFrom(realpath(self::PATH_VIEWS), 'laravel-components-library');
        Blade::component(Textarea::class,'customtextarea' );
    }
}

My blade component is located at: resources/views/components/form/customtextarea.blade.php

0 likes
7 replies
bugsysha's avatar

In my package service provider I have following:

public function boot(): void
{
  $this->loadViewComponentsAs('bugsysha', $this->viewComponents());
}

protected function viewComponents(): array
{
  return [
    \Bugsysha\View\Components\Button::class,
  ];
}

And then in blade files:

<x-bugsysha-button/>
1 like
pieterdejong's avatar

If i try it your way, i get the same error View [components.form.customtextarea] not found.

What path do you have in you Button class?

bugsysha's avatar
public function render(): Renderable
{
  return view('bugsysha::_partials.button-submit');
}
tykus's avatar
tykus
Best Answer
Level 104

This will namespace your views:

$this->loadViewsFrom(realpath(self::PATH_VIEWS), 'laravel-components-library');

so this is how to locate the view template (assuming the components.form.customtextarea path is relative to the root realpath(self::PATH_VIEWS)

return view('laravel-components-library::components.form.customtextarea');

Also, I believe this is incorrect:

Blade::component(Textarea::class,'customtextarea' );

// should be

Blade::component('customtextarea', Textarea::class);
1 like
pieterdejong's avatar

Thanks for your response, this made it more clear what the loadViewsFrom method is doing.

What fixed the problem was a slash.

private const PATH_VIEWS = __DIR__ . '/../resources/views/';
// Instead of
private const PATH_VIEWS = __DIR__ . '../resources/views/';

And for your syntax suggestion, both seem to work strangely. Documentation says differently than my IDE

Reinis.lucis's avatar

This is how I usually register component views for my packages. Replace myPackage with your desired alias:

    public function boot()
    {
        $this->loadViewsFrom(__DIR__.'/../resources/views', 'myPackage');
		$this->configureComponents();
	}
    protected function configureComponents()
    {
		$this->callAfterResolving(BladeCompiler::class, function () {
			$this->registerComponent('button');
			// Register other components here
		});
	}
    protected function registerComponent(string $component)
    {
        Blade::component('myPackage::components.'.$component, 'mypackage-'.$component);
    }

And in blade files:

<x-myPackage-button />
4 likes
pieterdejong's avatar

Problem solved, thanks everybody.

I don't know how to mark this as solved :s haha

Please or to participate in this conversation.