F
Filament•16mo ago
DarkKnight

Action with AlpineJS

My issue is that when I click on the empty part of the widget its like I pressed the action. In other words, the action is supposed to do something, and whether I press the action or the empty parts of the widget, its the same. Any idea why? Im thinking it has something to do with the <div> but I dont know how else to structure it.
<x-filament-widgets::widget>
<div wire:poll="stats" x-data="{
isPlaying: false,
playRadio: function() {
const mediaPlayer = this.$refs.radioPlayer; // Use Alpine.js $refs
if (mediaPlayer) {
mediaPlayer.play()
.catch(error => {
// Handle the error (e.g., display a message to the user)
console.error('Error playing audio:', error);
});
}
}
}">

<!-- Go to the radio page, using inspect element find the audio file -->
<audio id="radioPlayer" x-ref="radioPlayer">
<source src="https://live.akous.gr/akousbreeze" type="audio/mpeg">
Your browser does not support the audio element.
</audio>

<x-filament::section>
<div wire:poll="stats">
Song: {{ $this->stats()['songTitle'] }}
</div>

<!-- Trigger the action when the section is clicked -->
<div x-on:click="playRadio()">
{{ $this->testAction }}
<x-filament-actions::modals />
<!-- Remove $this->testAction expression -->
</div>

</x-filament::section>
</div>
</x-filament-widgets::widget>
<x-filament-widgets::widget>
<div wire:poll="stats" x-data="{
isPlaying: false,
playRadio: function() {
const mediaPlayer = this.$refs.radioPlayer; // Use Alpine.js $refs
if (mediaPlayer) {
mediaPlayer.play()
.catch(error => {
// Handle the error (e.g., display a message to the user)
console.error('Error playing audio:', error);
});
}
}
}">

<!-- Go to the radio page, using inspect element find the audio file -->
<audio id="radioPlayer" x-ref="radioPlayer">
<source src="https://live.akous.gr/akousbreeze" type="audio/mpeg">
Your browser does not support the audio element.
</audio>

<x-filament::section>
<div wire:poll="stats">
Song: {{ $this->stats()['songTitle'] }}
</div>

<!-- Trigger the action when the section is clicked -->
<div x-on:click="playRadio()">
{{ $this->testAction }}
<x-filament-actions::modals />
<!-- Remove $this->testAction expression -->
</div>

</x-filament::section>
</div>
</x-filament-widgets::widget>
35 Replies
DarkKnight
DarkKnightOP•16mo ago
Because of this
No description
DarkKnight
DarkKnightOP•16mo ago
was thinking of doing something like this, but it didnt work
public function testAction(): Action
{
return Action::make('playRadio')
->label("Breezer Radio")
->extraAttributes([
'x-on:click' => 'playRadio()',
])
->button();
}
public function testAction(): Action
{
return Action::make('playRadio')
->label("Breezer Radio")
->extraAttributes([
'x-on:click' => 'playRadio()',
])
->button();
}
Can anyone pls help?
Patrick Boivin
Patrick Boivin•16mo ago
Instead of the div with {{ $this->testAction }}, I think you could use a Filament button instead:
<x-filament::button x-on:click="playRadio()">
Play
</x-filament::button>
<x-filament::button x-on:click="playRadio()">
Play
</x-filament::button>
DarkKnight
DarkKnightOP•16mo ago
This does the job. Thank you. :) One more thing. I might ive missed it in the docs, but how do I import code from a js file to blade? I dont want to have all of my code in header. For example import it from resources/js/player.js
DarkKnight
DarkKnightOP•16mo ago
Nice Correct me if Im wrong, but should there be a specific structure to the JS file? For example, this is the first line in my JS file:
const audioElement = this.$refs.item;
const audioElement = this.$refs.item;
div x-data="{}"
x-init="item"
x-load-js="[@js(\Filament\Support\Facades\FilamentAsset::getScriptSrc('test-script'))]"
div x-data="{}"
x-init="item"
x-load-js="[@js(\Filament\Support\Facades\FilamentAsset::getScriptSrc('test-script'))]"
But I get error in console: Uncaught TypeError: Cannot read properties of undefined (reading 'item')
Patrick Boivin
Patrick Boivin•16mo ago
Yeah, that's not going to work. But you're pretty close!
Patrick Boivin
Patrick Boivin•16mo ago
Your JS file should register an Alpine component. Like the first example here with Alpine.data() https://alpinejs.dev/globals/alpine-data
DarkKnight
DarkKnightOP•16mo ago
Yeah I figured 😅 Ahhh I see
Patrick Boivin
Patrick Boivin•16mo ago
If your component is for example Alpine.data('audioElement', ...), then you can use this directly in x-data="audioElement"
DarkKnight
DarkKnightOP•16mo ago
Got itt. I will give this a try. Thank you!! amazingg. It worked! Could I also use AlpineComponent instead? I have this js code in the public/js/app/local-test-script.js directory
document.addEventListener('alpine:init', () => {
Alpine.data('audioElement', () => ({
test() {
console.log("Success");
},
}))
})
document.addEventListener('alpine:init', () => {
Alpine.data('audioElement', () => ({
test() {
console.log("Success");
},
}))
})
And the blade file:
<x-filament::button @click="test">
Test Button
</x-filament::button>
<x-filament::button @click="test">
Test Button
</x-filament::button>
Yet when I check the console, it cant find test I also tried including the function in
x-init="test()"
x-init="test()"
Patrick Boivin
Patrick Boivin•16mo ago
Make sure the button is inside of the element with x-data="audioElement"
DarkKnight
DarkKnightOP•16mo ago
It is (changed it a bit):
<div x-data="audioElement" x-load-js="[@js(\Filament\Support\Facades\FilamentAsset::getScriptSrc('local-test-script'))]">
<x-filament::button @click="test">
Play
</x-filament::button>
</div>
<div x-data="audioElement" x-load-js="[@js(\Filament\Support\Facades\FilamentAsset::getScriptSrc('local-test-script'))]">
<x-filament::button @click="test">
Play
</x-filament::button>
</div>
But it somehow STILL doesnt find it. And I have run php artisan filament:assets WTFFFF. So I had 2 JS files, and apparently even though i explicitly say which JS file to request, it requests a COMPLETELY different JS file. UHH. So apparently if you have 2 JS files that have the same component 'audioElement', even if you call a SPECIFIC JS file, it will call the last one that is sees in the directory, even if you didnt call the file?? Pls correct me if Im wrong but that's what I understand
Patrick Boivin
Patrick Boivin•16mo ago
I don't understand where the 2 files are coming from...
DarkKnight
DarkKnightOP•16mo ago
Yeah they were in the same directory, but they both had audioElement as component But with different Alpine code. Well, the blade file just took the last file with the audioElement as component
Patrick Boivin
Patrick Boivin•16mo ago
Ok... strange I don't have much experience with x-load-js to be honest... I usually just load the JS file from a service provider.
DarkKnight
DarkKnightOP•16mo ago
Might do that Thank you for your help so far! One more thing. I have my own theme, and I cant seem to be able to apply custom styles in the blade components. For example:
<x-filament-widgets::widget class="test-widget"
<x-filament-widgets::widget class="test-widget"
.test-widget {
position: fixed;
left: 10px;
bottom: 10px;
width: calc(100% - 20px);
}
.test-widget {
position: fixed;
left: 10px;
bottom: 10px;
width: calc(100% - 20px);
}
And of course npm run build. Do I have to register the css as well?
Patrick Boivin
Patrick Boivin•16mo ago
Otherwise yeah, you can also load an extra CSS file from a service provider
DarkKnight
DarkKnightOP•16mo ago
I have created a custom theme and I also registed it in the admin panel
->viteTheme('resources/css/filament/app/theme.css')
->viteTheme('resources/css/filament/app/theme.css')
As far as I can tell, it only work for overriding classes that already exist in filament, such as fi-section-content-ctn
DarkKnight
DarkKnightOP•16mo ago
I mean yeah I load the css, but how do I know where to place the .test-widget for example? This just tells me that I need to load it
No description
awcodes
awcodes•16mo ago
I don’t think the widget component inherits class attributes on its root. So just make a Div inside and add you’re classes there. You should be able to add theme just fine to your alpine component div.
DarkKnight
DarkKnightOP•16mo ago
I already tried this, and at the time I thought I didnt work. but now, for debugging purposes, I added a red background to the class, and now I see that it indeed appears behind the fi-section-content-ctn
Patrick Boivin
Patrick Boivin•16mo ago
As far as I can tell, it only work for overriding classes that already exist in filament, such as fi-section-content-ctn
This could be related to the content property of the tailwind config. Did you update it to include the views from your project?
DarkKnight
DarkKnightOP•16mo ago
I think so yes:
export default {
presets: [preset],
content: [
'./app/Filament/**/*.php',
'./resources/views/filament/**/*.blade.php', // <--------------
'./vendor/filament/**/*.blade.php',
'./vendor/awcodes/filament-curator/resources/views/**/*.blade.php',
'./vendor/awcodes/filament-quick-create/resources/views/**/*.blade.php',
],
}
export default {
presets: [preset],
content: [
'./app/Filament/**/*.php',
'./resources/views/filament/**/*.blade.php', // <--------------
'./vendor/filament/**/*.blade.php',
'./vendor/awcodes/filament-curator/resources/views/**/*.blade.php',
'./vendor/awcodes/filament-quick-create/resources/views/**/*.blade.php',
],
}
Patrick Boivin
Patrick Boivin•16mo ago
Yeah, looks good
DarkKnight
DarkKnightOP•16mo ago
I will try and explain what Im looking for to the best of my abilities. What i need is a class selector that inherits all the properties of fi-section-content-ctn. I can make whatever modifications I want to it (the new class), and it wont affect fi-section-content-ctn at all
DarkKnight
DarkKnightOP•16mo ago
Therefore it works like a custom version of fi-section-content-ctn.
No description
awcodes
awcodes•16mo ago
Not sure I’m really understanding the issue, but if it helps nothing in filament actually is based on any of the fi classes. They are merely a way to hook onto the components to override the default styling with your own stylesheet.
DarkKnight
DarkKnightOP•16mo ago
Ok so basically I want to have a custom version of fi-section-content-ctn but ONLY to that div that shown above. I dont want to touch the original fi-section-content-ctn.
awcodes
awcodes•16mo ago
So add a class higher up then your can scope it. That’s standard css cascade. Put a Div in your widget with a class of “whatever” then in your css .whatever .fi-section… it will be scoped.
DarkKnight
DarkKnightOP•16mo ago
I tried, but
<x-filament-widgets::widget>
<div class="test-widget">

<x-filament::section>
<div>

</div>

</x-filament::section>
</div>
</x-filament-widgets::widget>
<x-filament-widgets::widget>
<div class="test-widget">

<x-filament::section>
<div>

</div>

</x-filament::section>
</div>
</x-filament-widgets::widget>
awcodes
awcodes•16mo ago
Yea. So .test-widget .fi-etc This is really css and not filament related. You need to figure out the cascade based on your app.
DarkKnight
DarkKnightOP•16mo ago
And I assume I have to apply this to the theme as well?
awcodes
awcodes•16mo ago
It should be in a theme either way. There is no too. It’s either a theme or it’s not. A theme replaces filaments default theme even if it’s based around the default theme. That’s just how tailwind works. When you make a custom theme you aren’t replacing just part of the default stylesheet that filament ships with. It’s not an addition. It’s a total replacement.

Did you find this page helpful?