Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

valentin_vranic's avatar

Livewire + wavesurfer

I'm rendering conditionally the livewire view, because previously I'm generating wav files for wavesurfer. After the generating method the render is called automatically because I fill up 2 lw properties. However in devtools console I'm getting an error, the Container could not be found

<div>
    <div id="waveform_left"></div>
    <div id="waveform_right"></div>
</div>

@assets
<script src="https://unpkg.com/wavesurfer.js@7"></script>
<script src="https://unpkg.com/wavesurfer.js@7/dist/plugins/regions.min.js"></script>
<script src="https://unpkg.com/wavesurfer.js@7/dist/plugins/hover.min.js"></script>
@endassets

@script
<script>
    const ws_options = {
        cursorWidth: 3,
        cursorColor: '#e50d0d',
        waveColor: '#005ce6',
        progressColor: '#000080',
        // splitChannels: true,
        height: 150,
    }

    const audioUrlLeft = '{{ asset("storage/rtp-tools/tmp/") }}/' + $wire.leftWSPath;
    const audioUrlRight = '{{ asset("storage/rtp-tools/tmp/") }}/' + $wire.rightWSPath;
    console.log(audioUrlLeft)
    console.log(audioUrlRight)
    let ws_left = WaveSurfer.create({
        ...ws_options,
        container: '#waveform_left',
        url: audioUrlRight,
        // plugins: [hover],
    })

</script>
@endscript

The audioUrlLeft and audioUrlRight are filled properly, and with existing wav files

0 likes
1 reply
LaryAI's avatar
Level 58

The error "the Container could not be found" typically indicates that the WaveSurfer instance is trying to initialize before the DOM element it references is available. This can happen if the script runs before the Livewire component has fully rendered.

To ensure that the WaveSurfer instances are created only after the Livewire component has rendered, you can use Livewire's @this.on('event-name', callback) to listen for a custom event that you trigger after the component has rendered. Here's how you can modify your code to achieve this:

  1. Emit a custom event from your Livewire component after the properties are set and the view is rendered.
  2. Listen for this event in your JavaScript and initialize WaveSurfer only after the event is received.

Here's an example of how you can implement this:

Livewire Component (PHP)

class YourComponent extends \Livewire\Component
{
    public $leftWSPath;
    public $rightWSPath;

    public function generateWavFiles()
    {
        // Your logic to generate wav files and set $leftWSPath and $rightWSPath

        // Emit an event after the properties are set
        $this->emit('wavFilesGenerated');
    }

    public function render()
    {
        return view('livewire.your-component');
    }
}

Blade View

<div>
    <div id="waveform_left"></div>
    <div id="waveform_right"></div>
</div>

@assets
<script src="https://unpkg.com/wavesurfer.js@7"></script>
<script src="https://unpkg.com/wavesurfer.js@7/dist/plugins/regions.min.js"></script>
<script src="https://unpkg.com/wavesurfer.js@7/dist/plugins/hover.min.js"></script>
@endassets

@script
<script>
    document.addEventListener('livewire:load', function () {
        @this.on('wavFilesGenerated', function () {
            const ws_options = {
                cursorWidth: 3,
                cursorColor: '#e50d0d',
                waveColor: '#005ce6',
                progressColor: '#000080',
                height: 150,
            };

            const audioUrlLeft = '{{ asset("storage/rtp-tools/tmp/") }}/' + @this.get('leftWSPath');
            const audioUrlRight = '{{ asset("storage/rtp-tools/tmp/") }}/' + @this.get('rightWSPath');
            console.log(audioUrlLeft);
            console.log(audioUrlRight);

            let ws_left = WaveSurfer.create({
                ...ws_options,
                container: '#waveform_left',
                url: audioUrlLeft,
            });

            let ws_right = WaveSurfer.create({
                ...ws_options,
                container: '#waveform_right',
                url: audioUrlRight,
            });
        });
    });
</script>
@endscript

Explanation:

  1. Livewire Component (PHP): After generating the WAV files and setting the properties, emit a custom event wavFilesGenerated.
  2. Blade View: Listen for the livewire:load event to ensure Livewire is fully loaded. Then, listen for the wavFilesGenerated event to initialize the WaveSurfer instances only after the properties are set and the view is rendered.

This approach ensures that the WaveSurfer instances are created only after the necessary DOM elements are available, preventing the "Container could not be found" error.

Please or to participate in this conversation.