We help IT Professionals succeed at work.

Laravelcollective/html form 6 - Custom Macro or Component - Class not found error

Ricky Nguyen
Ricky Nguyen asked
on
Medium Priority
57 Views
Last Modified: 2020-02-25
Hi Experts,

The Problem
I'm trying to create a custom Laravel/Collective 6 form component as per instruction here.

I installed the Laravel/Collective package as per the previous link instruction using:
$ composer require laravelcollective/html

Open in new window


I have no problems with using the form as it seems to work just fine. I've only encountered errors when trying to register a macro or component to App\Providers\AppServicePrivider.php boot function with:
Form::component('bsText', 'components.form.text', ['name', 'value', 'attributes']);

Open in new window


This is what I see:
laravelcollective error
When trying to load the custom component I get the following error:
 Laravelcollective class error

What I've Tested
When checking previous laravelcollective version, namely, v5.6 and prior, I see the following instructions:
Laravel form v5.6 installation instruction
I've tried adding those entries to their respective locations in providers and aliases but it did not seem to help.


I'm not sure what I'm missing, Can you please help point me in the right direction?

Many thanks,
Ricky
Comment
Watch Question

CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019

Commented:
Hey Ricky,

Your AppServiceProvider is namespaced to App\Providers, so currently your code is looking for a class with a fully qualified name of App\Providers\Form, which clearly doesn't exist.

You need to tell your code to root the namespace by prefixing the Form call with a backslash:

public function boot()
{
    \Form::component('bsText', 'components.form.text', ['name', 'value', 'attributes']);
}

Open in new window

CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019

Commented:
FYI - if you don't want to NameSpace your Form, you can just import the Form at the start of the AppServiceProvider:

<?php
namespace App\Providers;

use Form;

class AppServiceProvider extends ServiceProvider
{

Open in new window

Now you can use Form without the leasing backslash:

public function boot()
{
    Form::component('bsText', 'components.form.text', ['name', 'value', 'attributes']);
}

Open in new window

Author

Commented:
Hi Chris, thanks you for your help, can you please show me how to import the form to the start of AppServiceProvider? I'm new to Laravel and having trouble understanding its infrastructure. How can I find out where Laravelcollective 6 forms are located?

Do I point it to this location for htmlserviceprovider.php?
folder location
CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019
Commented:
Hey Ricky,

No worries. You're not actually importing a file in the traditional sense of the word - you're importing a NameSpace. If you look at the top of your AppServiceProvider file, you'll see something like this:

<?php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{

Open in new window

That use statement is importing a NameSpace so that you can use classes within that NameSpace. That's exactly what you need to do so that you can use the classes from the Form namespace, so all you need to do is add use Form to it (you can do this because you've already aliased the full class to the name of 'Form')

<?php
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Form;

class AppServiceProvider extends ServiceProvider
{

Open in new window

Author

Commented:
It's giving me this now:
lc-error.PNG
My users_detail blade file is this:
@section('contents')

        {{ Form::bsText('first_name') }}


  @stop

Open in new window



All that I'm trying to do is follow the document's instructions. Is this a related problem?

Author

Commented:
I replaced this:
Form::component('bsText', 'components.form.text', ['name', 'value', 'attributes']);

Open in new window


with this:
Form::component('bsText', 'components.form.text', ['name', 'value' => null, 'attributes' => []]);

Open in new window


And it works!
results.PNG
Thanks for your help Chris.

Cheers mate,
Ricky

Author

Commented:
Thanks so much for your help!
CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019

Commented:
OK Ricky,

There are a few moving parts to your code, so I'll run through them to help you understand what's going on.

First off, you're registering a component:

Form::component('bsText', 'components.form.text', ['name', 'value', 'attributes']);

This means that in your View, you can create an instance of that component. When you try to create that instance it will take 3 arguments (name, value and atributes) and render the Blade file stored at components/form/text.blade.php.

If we look at that file, you can hopefully see how these 3 arguments are used:

<div class="form-group">
    {{ Form::label($name, null, ['class' => 'control-label']) }}
    {{ Form::text($name, $value, array_merge(['class' => 'form-control'], $attributes)) }}
</div>

Open in new window

It creates a Label using the name argument, and creates a text input using the name, the value (default value of the input) and the attributes. The attributes argument should be an array and this allows you to pass in additional information when you create your bsText component:

So for example, you could do this:

{{ Form::bsText('first_name', 'Chris', ['class' => 'testInput'] }}

You can see we're passing in all three arguments there and the final output would be a label with a name of fisrt_name, and an input with a name of first_name, a default value of Chris and a class of testInput.

In you example, you're not passing in all three arguments, so it can't merge the $attributes with anything because it doesn't exist. You can get around this by either passing in an empty array and default value:

{{ Form::bsText('first_name', null, [] ) }}

Or by defining your component with default values:

Form::component('bsText', 'components.form.text', ['name', 'value' => null, 'attributes' => []);

Either way will work
CERTIFIED EXPERT
Most Valuable Expert 2018
Distinguished Expert 2019

Commented:
Excellent - looks like you figured out the deafult value whilst I was typing.

Glad I could help :)