Plugin development: JS file net::ERR_ABORTED 404 (Not Found)

<?php

namespace TheThunderTurner\FilamentLatex;

use Filament\Support\Assets\AlpineComponent;
use Filament\Support\Facades\FilamentAsset;
use Livewire\Livewire;
use Spatie\LaravelPackageTools\Package;
use Spatie\LaravelPackageTools\PackageServiceProvider;

class FilamentLatexServiceProvider extends PackageServiceProvider
{
public static string $name = 'filament-latex';

public function configurePackage(Package $package): void
{
$package->name(static::$name)
->hasViews()
->hasTranslations();
}

public function packageBooted(): void
{
Livewire::component('filament-latex', FilamentLatex::class);

FilamentAsset::register(
assets: [
AlpineComponent::make('filament-latex', __DIR__ . '/../resources/dist/filament-latex.js'),
],
package: 'thethunderturner/filament-latex'
);
}
}
<?php

namespace TheThunderTurner\FilamentLatex;

use Filament\Support\Assets\AlpineComponent;
use Filament\Support\Facades\FilamentAsset;
use Livewire\Livewire;
use Spatie\LaravelPackageTools\Package;
use Spatie\LaravelPackageTools\PackageServiceProvider;

class FilamentLatexServiceProvider extends PackageServiceProvider
{
public static string $name = 'filament-latex';

public function configurePackage(Package $package): void
{
$package->name(static::$name)
->hasViews()
->hasTranslations();
}

public function packageBooted(): void
{
Livewire::component('filament-latex', FilamentLatex::class);

FilamentAsset::register(
assets: [
AlpineComponent::make('filament-latex', __DIR__ . '/../resources/dist/filament-latex.js'),
],
package: 'thethunderturner/filament-latex'
);
}
}
export default function clockWidget() {
return {
time: new Date().toLocaleTimeString(),
init() {
setInterval(() => {
this.time = new Date().toLocaleTimeString();
}, 1000);
}
}
}
export default function clockWidget() {
return {
time: new Date().toLocaleTimeString(),
init() {
setInterval(() => {
this.time = new Date().toLocaleTimeString();
}, 1000);
}
}
}
<x-filament-panels::page>
<x-filament::section>
<x-slot name="heading">
Test
</x-slot>

<div
x-ignore
ax-load
ax-load-src="{{ \Filament\Support\Facades\FilamentAsset::getAlpineComponentSrc('filament-latex', 'thethunderturner/filament-latex') }}"
x-data="clockWidget()"
class="text-center"
>
<p class="text-xl" x-text="time"></p>
</div>
</x-filament::section>
</x-filament-panels::page>
<x-filament-panels::page>
<x-filament::section>
<x-slot name="heading">
Test
</x-slot>

<div
x-ignore
ax-load
ax-load-src="{{ \Filament\Support\Facades\FilamentAsset::getAlpineComponentSrc('filament-latex', 'thethunderturner/filament-latex') }}"
x-data="clockWidget()"
class="text-center"
>
<p class="text-xl" x-text="time"></p>
</div>
</x-filament::section>
</x-filament-panels::page>
36 Replies
Matthew
MatthewOP4w ago
Error: GET http://localhost:8000/js/thethunderturner/filament-latex/components/filament-latex.js?v=dev-main net::ERR_ABORTED 404 (Not Found) Anyone?
awcodes
awcodes4w ago
php artisan filament:assets Registering plugin scripts will publish them to the public folder when someone installs your plugin. During development though you need to manually publish it anytime you make changes.
Matthew
MatthewOP2w ago
Ah yess, I forgot about that. I will try as soon as I get home Thx I have another question.
<x-filament-panels::page>
<x-filament::section>
<x-slot name="heading">CodeMirror Integration</x-slot>

<div class="grid grid-flow-col justify-stretch gap-4">
<div
x-data="codeEditor"
id="codemirror-container"
ax-load-src="{{ \Filament\Support\Facades\FilamentAsset::getAlpineComponentSrc('filament-latex', 'thethunderturner/filament-latex') }}"
>

</div>

<div class="border rounded p-4">02</div>
</div>
</x-filament::section>
</x-filament-panels::page>
<x-filament-panels::page>
<x-filament::section>
<x-slot name="heading">CodeMirror Integration</x-slot>

<div class="grid grid-flow-col justify-stretch gap-4">
<div
x-data="codeEditor"
id="codemirror-container"
ax-load-src="{{ \Filament\Support\Facades\FilamentAsset::getAlpineComponentSrc('filament-latex', 'thethunderturner/filament-latex') }}"
>

</div>

<div class="border rounded p-4">02</div>
</div>
</x-filament::section>
</x-filament-panels::page>
import { EditorView, basicSetup } from 'codemirror'
import { javascript } from '@codemirror/lang-javascript'
import { EditorState } from '@codemirror/state'

document.addEventListener('alpine:init', () => {
Alpine.data('codeEditor', () => ({
init() {
new EditorView({
state: EditorState.create({
doc: 'Hello World',
extensions: [basicSetup, javascript()]
}),
parent: this.$el
})
}
}))
})
import { EditorView, basicSetup } from 'codemirror'
import { javascript } from '@codemirror/lang-javascript'
import { EditorState } from '@codemirror/state'

document.addEventListener('alpine:init', () => {
Alpine.data('codeEditor', () => ({
init() {
new EditorView({
state: EditorState.create({
doc: 'Hello World',
extensions: [basicSetup, javascript()]
}),
parent: this.$el
})
}
}))
})
I get an error in my blade file that cpeEditor isnt recognized. Why is that the case?
awcodes
awcodes2w ago
Probably because your script it getting loaded after alpine has initialized so theirs no reference to it.
Matthew
MatthewOP2w ago
yeah I managed to fix it with:
import { EditorView, basicSetup } from 'codemirror'
import { javascript } from '@codemirror/lang-javascript'
import { EditorState } from '@codemirror/state'

export default function codeEditor() {
return {
init() {
new EditorView({
state: EditorState.create({
doc: 'Hello World',
extensions: [basicSetup, javascript()]
}),
parent: this.$el
})
}
}
}
import { EditorView, basicSetup } from 'codemirror'
import { javascript } from '@codemirror/lang-javascript'
import { EditorState } from '@codemirror/state'

export default function codeEditor() {
return {
init() {
new EditorView({
state: EditorState.create({
doc: 'Hello World',
extensions: [basicSetup, javascript()]
}),
parent: this.$el
})
}
}
}
I cant use state as input param to codeEditor() function though like here
// Import any external JavaScript libraries from NPM here.

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

// You can define any other Alpine.js properties here.

init: function () {
// Initialise the Alpine component here, if you need to.
},

// You can define any other Alpine.js functions here.
}
}
// Import any external JavaScript libraries from NPM here.

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

// You can define any other Alpine.js properties here.

init: function () {
// Initialise the Alpine component here, if you need to.
},

// You can define any other Alpine.js functions here.
}
}
awcodes
awcodes2w ago
Check the editor docs I’m sure it has events you can use to tie the state back. That’s what I have to do with Tiptap.
Matthew
MatthewOP2w ago
Thanks, one more thing. How can I use a custom icon as a navigation icon?
awcodes
awcodes2w ago
It supports the path to a view file. You could just put your svg icon in there. This is what I did when I was working on a codemirror plugin.
init: function () {
this.setLanguage(this.language);
let _this = this;

this.editor = new EditorView({
parent: this.$refs.editor,
defaultLineHeight: 1,
state: EditorState.create({
doc: this.state,
extensions: [
lineNumbers(),
EditorView.lineWrapping,
EditorView.updateListener.of(function(e) {
_this.state = e.state.doc.toString();
}),
….
init: function () {
this.setLanguage(this.language);
let _this = this;

this.editor = new EditorView({
parent: this.$refs.editor,
defaultLineHeight: 1,
state: EditorState.create({
doc: this.state,
extensions: [
lineNumbers(),
EditorView.lineWrapping,
EditorView.updateListener.of(function(e) {
_this.state = e.state.doc.toString();
}),
….
Matthew
MatthewOP2w ago
like this?
public static function getNavigationIcon(): string | Htmlable | null
{
return 'vendor/codeat3/blade-file-icons/resources/svg/latex.svg';
}
public static function getNavigationIcon(): string | Htmlable | null
{
return 'vendor/codeat3/blade-file-icons/resources/svg/latex.svg';
}
It doesnt work or should I maybe move the svg to public? ah, I see... I will definitely give this a try!
awcodes
awcodes2w ago
No, have to crate a blade file then just put the svg code in that blade file. And point to the blade file.
Matthew
MatthewOP2w ago
Ah, I see now. I cant just download the svgs from composer and then point to them
awcodes
awcodes2w ago
You can also create a custom set that uses blade-icons and inject them that way. That’s what I’m doing in my next version of Tiptap editor.
Matthew
MatthewOP2w ago
like this:
No description
Matthew
MatthewOP2w ago
But its still not found
awcodes
awcodes2w ago
Hmm. I would expect that to work.
Matthew
MatthewOP2w ago
i have an idea
Matthew
MatthewOP2w ago
I tried adding this
No description
Matthew
MatthewOP2w ago
But its still not seen
awcodes
awcodes2w ago
Yea. I can try some things tomorrow. And it’s probably overkill for your need but you can source dive this to see how to tap into blade icons to create a custom set and inject it. https://github.com/awcodes/scribble Start in the register method of the service provider.
LeandroFerreira
return 'fileicon-latex'; actually
Matthew
MatthewOP2w ago
like this?
No description
Matthew
MatthewOP2w ago
Still not found Svg by name "fileicon-latex" from set "default" not found. I figured it out 💀. You return the view, not just the path
public static function getNavigationIcon(): string | Htmlable | null
{
return view('filament-latex::svg.latex');
}
public static function getNavigationIcon(): string | Htmlable | null
{
return view('filament-latex::svg.latex');
}
LeandroFerreira
did you run composer require codeat3/blade-file-icons? Because if you are using this package, I think you should be able to use fileicon-latex
Matthew
MatthewOP2w ago
yep, I had it installed It didnt work though
LeandroFerreira
let me try it.. one sec
LeandroFerreira
that works
public static function getNavigationIcon(): ?string
{
return 'fileicon-latex';
}
public static function getNavigationIcon(): ?string
{
return 'fileicon-latex';
}
No description
Matthew
MatthewOP2w ago
huuuuuuuuuuuuuuuuh? From a fresh plugin?
LeandroFerreira
ahh no, it is a Resource
Matthew
MatthewOP21h ago
bug report 👀 Hey, I just tried it on a resource, and it doesnt work :/ Currently I have this:
class ... extends Resource
{
public static function getNavigationIcon(): string | Htmlable | null
{
return view('filament-latex::svg.latex');
}
}
class ... extends Resource
{
public static function getNavigationIcon(): string | Htmlable | null
{
return view('filament-latex::svg.latex');
}
}
but then github actions give me this error
PHP Fatal error: Declaration of TheThunderTurner\FilamentLatex\Resources\FilamentLatexResource::getNavigationIcon():Illuminate\Contracts\Support\Htmlable|string|null must be compatible with Filament\Resources\Resource::getNavigationIcon(): ?string in /home/runner/work/filament-latex/filament-latex/src/Resources/FilamentLatexResource.php on line 29
PHP Fatal error: Declaration of TheThunderTurner\FilamentLatex\Resources\FilamentLatexResource::getNavigationIcon():Illuminate\Contracts\Support\Htmlable|string|null must be compatible with Filament\Resources\Resource::getNavigationIcon(): ?string in /home/runner/work/filament-latex/filament-latex/src/Resources/FilamentLatexResource.php on line 29
which I dont understand because the parent function is
public static function getNavigationIcon(): string | Htmlable | null
{
return static::$navigationIcon;
}
public static function getNavigationIcon(): string | Htmlable | null
{
return static::$navigationIcon;
}
awcodes
awcodes21h ago
Sounds like your icons aren’t getting registered with blade ui icons.
Matthew
MatthewOP21h ago
Do I have to do anything in my plugin's service provider?
awcodes
awcodes21h ago
Honestly not sure. Check the blade ui icon docs to make sure. If the icon package is included and registered correctly then you should just be able to use the icon name in the getNavigationIcon() override.
Matthew
MatthewOP19h ago
This is from the PackageServiveProvider
Matthew
MatthewOP19h ago
As you can see, its missing the resources/svg I think thats why it doesnt work on plugins... I tried on my dev app and it works, so 🤷
Want results from more Discord servers?
Add your server