Laravel-modules: Livewire Components

Created on 15 Nov 2020  路  11Comments  路  Source: nWidart/laravel-modules

If I want to add a livewire component at the moment, there isn't a simple way to do this and have those components exist within the modules structure

For example.

I'm using the Data Tables package

I want components for this to exist in [ModuleName]/Http/Livewire/

However because of the way Livewire searches for components this isn't possible

Now I can fix this by registering the components in my Modules/[modulename]/Provider/ServiceProvider

and add something like

Livewire::component('product-datatable', ProductDatatable::class);

but this is a lot of work if I have lots of components to add.

What would be better is if we inspected the [ModuleName]/Http/Livewire/
directory and automatically registered components.

The registration could first just convert the class name from camel case to kebab case
or we could look for a static componentName method

I'm willing to provide a PR for this.

Most helpful comment

I think it would be easier to add it as a command like this one:
php artisan module:make-livewire [component_name] [module_name]

For me, this issue is also important and this is why I am not using modular approach right now because I like Livewire and the simplicity it brings.

All 11 comments

I think it would be easier to add it as a command like this one:
php artisan module:make-livewire [component_name] [module_name]

For me, this issue is also important and this is why I am not using modular approach right now because I like Livewire and the simplicity it brings.

@zcwilt I'm using a custom service provider for livewire components registration. So, no need to register manually every time. It's working for me. You can try this.

Example:

Livewire Component Class - Modules\Contact\Http\Livewire\Frontend\Components\ContactForm

Use this component in the blade file like this - <livewire:contact::frontend.components.contact-form />

Register custom livewire service provider in the core modules service provider -

/**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->app->register(RouteServiceProvider::class);
        $this->app->register(CustomLivewireServiceProvider::class); // Add this line
    }

Custom Livewire Service Provider Class - Modules\Core\Providers\CustomLivewireServiceProvider

<?php

namespace Modules\Core\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Filesystem\Filesystem;

class CustomLivewireServiceProvider extends ServiceProvider
{
    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->loadComponents();
    }

    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return [];
    }

    protected function loadComponents()
    {
        $modules = \Module::toCollection();

        $filesystem = new Filesystem();

        $modules->map(function ($module) use ($filesystem) {
            $modulePath = $module->getPath();

            $moduleName = $module->getName();

            $path = $modulePath.'/Http/Livewire';

            $files = collect( $filesystem->isDirectory($path) ? $filesystem->allFiles($path) : [] );

            $files->map(function ($file) use ($moduleName, $path) {
                $componentPath = \Str::after($file->getPathname(), $path.'/');

                $componentClassPath = strtr( $componentPath , ['/' => '\\', '.php' => '']);

                $componentName = $this->getComponentName($componentClassPath, $moduleName);

                $componentClassStr = "\\Modules\\{$moduleName}\\Http\\Livewire\\".$componentClassPath;

                $componentClass = get_class(new $componentClassStr);

                $loadComponent = \Livewire::component($componentName, $componentClass);
            });
        });
    }

    protected function getComponentName($componentClassPath, $moduleName = null)
    {
        $dirs = explode('\\', $componentClassPath);

        $componentName = '';

        foreach ($dirs as $dir) {
            $componentName .= \Str::kebab( lcfirst($dir) ).'.';
        }

        $moduleNamePrefix = ($moduleName) ? \Str::lower($moduleName).'::' : null;

       return \Str::substr($moduleNamePrefix.$componentName, 0, -1);
    }
}

m Livewire Service Provider Class - Modules\Core\Providers\CustomLivewireService

Would you be able to PR it? I would love to see this in a future version of Laravel Modules

@FoksVHox Sure, I will provide PR for this very soon.

@FoksVHox I submitted a PR for Livewire Support. #1150

Modules\Channel\Providers\LivewireServiceProvider not found

@zcwilt I'm using a custom service provider for livewire components registration. So, no need to register manually every time. It's working for me. You can try this.

Example:

Livewire Component Class - Modules\Contact\Http\Livewire\Frontend\Components\ContactForm

Use this component in the blade file like this - <livewire:contact::frontend.components.contact-form />

Register custom livewire service provider in the core modules service provider -

/**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->app->register(RouteServiceProvider::class);
        $this->app->register(CustomLivewireServiceProvider::class); // Add this line
    }

Custom Livewire Service Provider Class - Modules\Core\Providers\CustomLivewireServiceProvider

<?php

namespace Modules\Core\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Filesystem\Filesystem;

class CustomLivewireServiceProvider extends ServiceProvider
{
    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->loadComponents();
    }

    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return [];
    }

    protected function loadComponents()
    {
        $modules = \Module::toCollection();

        $filesystem = new Filesystem();

        $modules->map(function ($module) use ($filesystem) {
            $modulePath = $module->getPath();

            $moduleName = $module->getName();

            $path = $modulePath.'/Http/Livewire';

            $files = collect( $filesystem->isDirectory($path) ? $filesystem->allFiles($path) : [] );

            $files->map(function ($file) use ($moduleName, $path) {
                $componentPath = \Str::after($file->getPathname(), $path.'/');

                $componentClassPath = strtr( $componentPath , ['/' => '\\', '.php' => '']);

                $componentName = $this->getComponentName($componentClassPath, $moduleName);

                $componentClassStr = "\\Modules\\{$moduleName}\\Http\\Livewire\\".$componentClassPath;

                $componentClass = get_class(new $componentClassStr);

                $loadComponent = \Livewire::component($componentName, $componentClass);
            });
        });
    }

    protected function getComponentName($componentClassPath, $moduleName = null)
    {
        $dirs = explode('\\', $componentClassPath);

        $componentName = '';

        foreach ($dirs as $dir) {
            $componentName .= \Str::kebab( lcfirst($dir) ).'.';
        }

        $moduleNamePrefix = ($moduleName) ? \Str::lower($moduleName).'::' : null;

       return \Str::substr($moduleNamePrefix.$componentName, 0, -1);
    }
}

I am getting error class of provider not found

Class '\Modules\Channel\Http\Livewire\C:\xampp\htdocs\boilerplate\Modules\Channel\Http\Livewire\Rule\FormComponent' not found

@aishwaryakumar-hub Did you face this error from this package?

https://github.com/mhmiton/laravel-modules-livewire

I solved finally

Was this page helpful?
0 / 5 - 0 ratings

Related issues

n4p4 picture n4p4  路  17Comments

echemik picture echemik  路  10Comments

githubmarau picture githubmarau  路  29Comments

designvoid picture designvoid  路  10Comments

KyawNaingTun picture KyawNaingTun  路  16Comments