Using a custom component in a Form

Hi - I think I've overlooked something here. I am creating a livewire-component to show an overview, which is then polled every 10 seconds. So I made a new component via php artisan make:livewire mycomponentand now I wanna use that within getFormSchema() inside a section, but it does not have the usual ::make() function, which all FilamentComponents have. Do I have to define a make-function myself or just use some Trait?
24 Replies
Patrick Boivin
You can wrap your Livewire component in a Filament form component. It's not ideal but easy to setup.
public static function form(Form $form): Form
{
return $form->schema([
MyComponentWrapper::make(),

// ...
public static function form(Form $form): Form
{
return $form->schema([
MyComponentWrapper::make(),

// ...
class MyComponentWrapper extends Component
{
protected string $view = 'my-component-wrapper';

// ...
}
class MyComponentWrapper extends Component
{
protected string $view = 'my-component-wrapper';

// ...
}
@livewire('my-component', [ ... ])
@livewire('my-component', [ ... ])
I think you could even use Component::make()->view( ... ) directly, if you don't need to encapsulate anything else in the form component.
awcodes
awcodes2y ago
just use a ViewField and set ->view('my-component.blade.php') and put <livewire:my-livewire-component/> in that blade file.
Patrick Boivin
But the ViewField requires a $name parameter, no?
awcodes
awcodes2y ago
Sorry, wrong class, you can use the View layout component. View::make('filament.forms.components.wizard') if you don't need schema you don't have to provide it. I don't think.
Husky110
Husky110OP2y ago
Perfect - Thanks guys! 🙂 I tried your approach, but it ends in the Page not beeing loaded (loading keeps on scrolling there...) view:
<livewire:container-full-status />
<div wire.poll.10s>
{{ $timestamp }}
</div>
<livewire:container-full-status />
<div wire.poll.10s>
{{ $timestamp }}
</div>
Component.php:
<?php

namespace App\Http\Livewire;

use Livewire\Component;

class ContainerFullStatus extends Component
{

public int $timeStamp;

public function mount()
{
$this->timeStamp = now()->getTimestamp();
}

public function render()
{
return view('components.m-components.sysinternals.container-full-status');
}
}
<?php

namespace App\Http\Livewire;

use Livewire\Component;

class ContainerFullStatus extends Component
{

public int $timeStamp;

public function mount()
{
$this->timeStamp = now()->getTimestamp();
}

public function render()
{
return view('components.m-components.sysinternals.container-full-status');
}
}
And I implemented it like this:
Section::make(m__('about.systemstatus.containerstatus.sectionheadline'))->columnSpan(2)
->schema([
View::make('components.my-components.sysinternals.container-full-status')
]),
Section::make(m__('about.systemstatus.containerstatus.sectionheadline'))->columnSpan(2)
->schema([
View::make('components.my-components.sysinternals.container-full-status')
]),
awcodes
awcodes2y ago
The wire poll needs to be inside your livewire components view. Not your view layout blade file.
Husky110
Husky110OP2y ago
Okay - now I am confused... For the page-loading - the render()-function was the problem there... Basically - what I want is a reuseable Livewire-Component... Where the polling does poll the component and not the full page...
awcodes
awcodes2y ago
Understandable, it’s hard to explain. In your form View::make() points to a blade file. That blade file has nothing in it but the <livewire> directive. That directive loads your livewire component’s blade file that has all you live wire stuff in it. So it’s two Separate files.
Husky110
Husky110OP2y ago
Ahhhhhh - okay, I think I get what are you are saying! One second! 😁
awcodes
awcodes2y ago
Basically you can’t load a livewire component directly in a form.
Husky110
Husky110OP2y ago
Okay. I moved the components view-file so it looks like this:
<div>
{{ $timestamp }}
</div>
<div>
{{ $timestamp }}
</div>
But now it tells me Undefined variable $timestamp... o.O shouldn't the mount-function define it?
awcodes
awcodes2y ago
wait. what are you trying to do exactly? is the timestamp a field on the record?
Husky110
Husky110OP2y ago
Nope - right now it's just a variable for me to test that polling works. 🙂 Okay - one step back. Right now it looks like this: Form-Page:
Section::make(m__('aboutmyapp.systemstatus.containerstatus.sectionheadline'))->columnSpan(2)
->schema([
View::make('components.my-components.sysinternals.container-full-status')
]),
Section::make(m__('aboutmyapp.systemstatus.containerstatus.sectionheadline'))->columnSpan(2)
->schema([
View::make('components.my-components.sysinternals.container-full-status')
]),
components.my-components.sysinternals.container-full-status looks like this:
<livewire:container-full-status />
<livewire:container-full-status />
the ContainerFullStatus.php like this:

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class ContainerFullStatus extends Component
{
public int $timeStamp;

public function mount()
{
$this->timeStamp = now()->getTimestamp();
}

public function render()
{
return view('livewire.container-full-status');
}
}

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class ContainerFullStatus extends Component
{
public int $timeStamp;

public function mount()
{
$this->timeStamp = now()->getTimestamp();
}

public function render()
{
return view('livewire.container-full-status');
}
}
And the livewire.container-full-status has this:
<div>
{{ $timestamp }}
</div>
<div>
{{ $timestamp }}
</div>
awcodes
awcodes2y ago
try
<div>
{{ $timeStamp }}
</div>
<div>
{{ $timeStamp }}
</div>
Husky110
Husky110OP2y ago
ah - the classic typo! thanks! 🙂 After that it works, but polling does not. Modified the component-view to
<div wire:poll>
{{ $timestamp }}
</div>
<div wire:poll>
{{ $timestamp }}
</div>
which (according to the livewire-docs) should change timestamp every 2 seconds, but it keeps beeing static. already tried the obligatory filament:upgrade...
Husky110
Husky110OP2y ago
Livewire
Polling | Livewire
A full-stack framework for Laravel that takes the pain out of building dynamic UIs.
awcodes
awcodes2y ago
mount only runs once when the component is initialized. you'll need to make a method to run on the interval that updates the $timeStamp property wire:poll="updateTimeStamp" something like that
Husky110
Husky110OP2y ago
okay... kinda weird... I tried it in a view directly before that and it updated the timestamp... huh... the more you know... thank you very much! 🙂 yep - that works. Kinda weird behavior tho that it needs a function, when the docs don't explicitly require one... 🙂
awcodes
awcodes2y ago
it's probably mentioned somewhere else in the docs. 🙂
Husky110
Husky110OP2y ago
I thought so aswell... But before that I tried this:
Section::make(m__('about.systemstatus.containerstatus.sectionheadline'))->columnSpan(2)
->schema([
View::make('components.my-components.sysinternals.container-full-status')->viewData(['timestamp' => now()->getTimestamp()])
]),
Section::make(m__('about.systemstatus.containerstatus.sectionheadline'))->columnSpan(2)
->schema([
View::make('components.my-components.sysinternals.container-full-status')->viewData(['timestamp' => now()->getTimestamp()])
]),
with components.my-components.sysinternals.container-full-status looking like this:
<div wire:poll="updateTimestamp">
{{ $timestamp }}
</div>
<div wire:poll="updateTimestamp">
{{ $timestamp }}
</div>
And that worked fine - so there was no need to define any function. But like I said - i wanted to poll only the component and not the whole page, so I guess that there is something going on in the background.
awcodes
awcodes2y ago
yea, the poll on the page in Filament is changing the property, but since you took it out of the "page" context, it needs it's own method for polling
Husky110
Husky110OP2y ago
ah okay! but I got that right, so that with the custom component and the custom function it only polls the component and not the whole page?
awcodes
awcodes2y ago
correct
Husky110
Husky110OP2y ago
thank you very much good sir! 🙂

Did you find this page helpful?