How can I get started with a JS field?

I want to create my own filament field (Slider) which is based on JS nouislider This is currently an Issue on github for filament 4.1. I want to get a jumpstart on this, and even if it doesnt get merged, at least I learned something new 😅 The problem is I have NO IDEA how to get started with javascript plugins. For starters, I added nouislider in the package.json. Furthermore, I've also create the Slider class, blade and JS file as follows: packages/forms/src/Components/Slider.php
<?php

namespace Filament\Forms\Components;

use Filament\Support\Concerns\HasExtraAlpineAttributes;

class Slider extends Field
{
use HasExtraAlpineAttributes;

/**
* @var view-string
*/
protected string $view = 'filament-forms::components.slider';

protected function setUp(): void
{
parent::setUp();
}
}
<?php

namespace Filament\Forms\Components;

use Filament\Support\Concerns\HasExtraAlpineAttributes;

class Slider extends Field
{
use HasExtraAlpineAttributes;

/**
* @var view-string
*/
protected string $view = 'filament-forms::components.slider';

protected function setUp(): void
{
parent::setUp();
}
}
packages/forms/resources/js/components/slider.js
export default function sliderFormComponent({ start = [20,80], min=0, max=100 }) {
return {
slider: null,

init: function () {
this.slider = document.getElementById('slider')

noUiSlider.create(this.slider, {
start: start,
connect: true,
range: {
'min': min,
'max': max
}
})
}
}
}
export default function sliderFormComponent({ start = [20,80], min=0, max=100 }) {
return {
slider: null,

init: function () {
this.slider = document.getElementById('slider')

noUiSlider.create(this.slider, {
start: start,
connect: true,
range: {
'min': min,
'max': max
}
})
}
}
}
packages/forms/resources/views/components/slider.blade.php
<x-dynamic-component :component="$getFieldWrapperView()" :field="$field">
<div
id="slider"
x-data="sliderFormComponent({ start: [20, 80], min: 0, max: 100 })"
x-init="init()"
ax-load-src="{{ \Filament\Support\Facades\FilamentAsset::getAlpineComponentSrc('slider', 'filament/forms') }}">
</div>
</x-dynamic-component>
<x-dynamic-component :component="$getFieldWrapperView()" :field="$field">
<div
id="slider"
x-data="sliderFormComponent({ start: [20, 80], min: 0, max: 100 })"
x-init="init()"
ax-load-src="{{ \Filament\Support\Facades\FilamentAsset::getAlpineComponentSrc('slider', 'filament/forms') }}">
</div>
</x-dynamic-component>
In the create page, I have the Slider field, but when the page is loaded I get this error: Alpine component with ID [slider] not found for package [filament/forms]. What am I missing? Can anyone help?
17 Replies
Matthew
MatthewOP4mo ago
Ok thanks.
@php
use Filament\Support\Facades\FilamentView;

$id = $getId();
$statePath = $getStatePath();
@endphp
<x-dynamic-component :component="$getFieldWrapperView()" :field="$field">
<div
id="slider"
ax-load
ax-load-src="{{ \Filament\Support\Facades\FilamentAsset::getAlpineComponentSrc('slider', 'filament/forms') }}"
x-data="sliderFormComponent({
state: $wire.{{ $applyStateBindingModifiers("\$entangle('{$statePath}')") }},
})"
x-ignore
>

</div>
</x-dynamic-component>
@php
use Filament\Support\Facades\FilamentView;

$id = $getId();
$statePath = $getStatePath();
@endphp
<x-dynamic-component :component="$getFieldWrapperView()" :field="$field">
<div
id="slider"
ax-load
ax-load-src="{{ \Filament\Support\Facades\FilamentAsset::getAlpineComponentSrc('slider', 'filament/forms') }}"
x-data="sliderFormComponent({
state: $wire.{{ $applyStateBindingModifiers("\$entangle('{$statePath}')") }},
})"
x-ignore
>

</div>
</x-dynamic-component>
export default function sliderFormComponent({ state }) {
return {
state,

slider: null,

init: function () {
this.slider = document.getElementById('slider')

noUiSlider.create(this.slider, {
start: [20,80],
connect: true,
range: {
'min': 0,
'max': 100
}
})
}
}
}
export default function sliderFormComponent({ state }) {
return {
state,

slider: null,

init: function () {
this.slider = document.getElementById('slider')

noUiSlider.create(this.slider, {
start: [20,80],
connect: true,
range: {
'min': 0,
'max': 100
}
})
}
}
}
But when I open the browser I get this on the console:
No description
Matthew
MatthewOP4mo ago
Which is weird because Ive already added the nouislider in the devdependencies
toeknee
toeknee4mo ago
It's not so weird, it can't find it... the url diesn't exist
Matthew
MatthewOP4mo ago
any idea why that is? Have I missed some step? I also ran node bin/build.js to create the slider.js in /dist
toeknee
toeknee4mo ago
Looks like your slider.js hasn't been deployed to /forms/components/
Matthew
MatthewOP4mo ago
No description
toeknee
toeknee4mo ago
You shouldn't be placing it there really as it's not part of the package why would it be put there? Have a look at how to include js in filament: https://filamentphp.com/docs/3.x/support/assets#registering-javascript-files
Matthew
MatthewOP4mo ago
Ive already added it in the FormsServiceProvider
Matthew
MatthewOP4mo ago
Matthew
MatthewOP4mo ago
Should it also be somewhere else?
Matthew
MatthewOP4mo ago
I kindda want to follow the same approach as these.
No description
Matthew
MatthewOP4mo ago
Hm okay, I ran php artisan filament:assets and now I get the JS file 🎉
Matthew
MatthewOP4mo ago
However, I dont see it
No description
Matthew
MatthewOP4mo ago
Could you help please? @toeknee
Matthew
MatthewOP4mo ago
@php
use Filament\Support\Facades\FilamentView;

$id = $getId();
$statePath = $getStatePath();
@endphp
<x-dynamic-component :component="$getFieldWrapperView()" :field="$field">
<div
ax-load
ax-load-src="{{ \Filament\Support\Facades\FilamentAsset::getAlpineComponentSrc('slider', 'filament/forms') }}"
x-data="sliderFormComponent({
state: $wire.{{ $applyStateBindingModifiers("\$entangle('{$statePath}')") }},
})"
x-ignore
>
<div id="slider">

</div>
</div>
</x-dynamic-component>
@php
use Filament\Support\Facades\FilamentView;

$id = $getId();
$statePath = $getStatePath();
@endphp
<x-dynamic-component :component="$getFieldWrapperView()" :field="$field">
<div
ax-load
ax-load-src="{{ \Filament\Support\Facades\FilamentAsset::getAlpineComponentSrc('slider', 'filament/forms') }}"
x-data="sliderFormComponent({
state: $wire.{{ $applyStateBindingModifiers("\$entangle('{$statePath}')") }},
})"
x-ignore
>
<div id="slider">

</div>
</div>
</x-dynamic-component>
import noUiSlider from 'nouislider';

export default function sliderFormComponent({ state }) {
return {
state,

slider: null,

init: function () {
this.slider = document.getElementById('slider')

console.log(this.slider);

noUiSlider.create(this.slider, {
start: [20, 80],
connect: true,
range: {
min: 0,
max: 100,
},
})
},
}
}
import noUiSlider from 'nouislider';

export default function sliderFormComponent({ state }) {
return {
state,

slider: null,

init: function () {
this.slider = document.getElementById('slider')

console.log(this.slider);

noUiSlider.create(this.slider, {
start: [20, 80],
connect: true,
range: {
min: 0,
max: 100,
},
})
},
}
}
No description
Matthew
MatthewOP4mo ago
Fixed it! Thanks for your help!
Want results from more Discord servers?
Add your server