#resize textarea with wire:stream

13 messages · Page 1 of 1 (latest)

fallen gust
#

I'm trying to get the textarea to resize every time it updates with wire:stream so that the height is adjusted, but I can't get it to work. If I write it manually, it adjusts, but when it updates automatically, it doesn't. Any ideas?

rotund streamBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> ✅ Mark Solution

fallen gust
#

This is my textarea

<textarea
                x-data="{
                        outputLogModel: $wire.$entangle('outputLog'),
                        resize() {
                            $el.style.height = '0px';
                            $el.style.height = $el.scrollHeight + 'px';
                        }
                    }"
                x-init="$nextTick(resize); $watch('outputLogModel', () => resize())"
                x-on:input="resize()"
                wire:stream="stream"
                wire:model="outputLog"
                rows="3"
                class="filament-input block w-full transition duration-75 rounded-lg shadow-sm focus:ring-primary-500 focus:border-primary-500 border-gray-300 resize-none"
            >{{ $outputLog }}</textarea>
timid laurel
#

Maybe listen/observe changes on the textarea like this (it's an function called in the x-data):

function textareaResizer() {
    return {
        init() {
            const observer = new MutationObserver(() => {
                this.resize();
            });

            observer.observe(messagesContainer, {
                childList: true,
                subtree: true,
            });

            // Initial resize, optional
            this.resize();
        },
        resize() {
            $el.style.height = '0px';
            $el.style.height = $el.scrollHeight + 'px';
        }
    };
}
#

It's from head, so it's maybe not working :/

fallen gust
# timid laurel Maybe listen/observe changes on the textarea like this (it's an function called ...

with this works perfectly, except that it doesn't continue all the way to the end of the viewport. That is, since the screen is larger, it can't be seen all the way to the bottom.:

<textarea
                x-data="{
                        outputLogModel: $wire.$entangle('outputLog'),
                        resize() {
                            $el.style.height = '0px';
                            $el.style.height = $el.scrollHeight + 'px';
                        }
                    }"
                x-init="$nextTick(() => {
                        const messagesContainer = $el;  // Asume que el contenedor es el propio textarea
                        const observer = new MutationObserver(() => {
                            resize();
                        });

                        observer.observe(messagesContainer, {
                            childList: true,
                            subtree: true,
                        });

                        // Initial resize
                        resize();
                    })"
                x-on:input="resize()"
                wire:stream="stream"
                autofocus
                rows="3"
                class="filament-input block w-full transition duration-75 rounded-lg shadow-sm focus:ring-primary-500 focus:border-primary-500 border-gray-300 resize-none"
            >{{ $outputLog }}</textarea>
timid laurel
#

Maybe using this function aside of the resize can help to scroll to bottom ?

scrollToBottom(container) {
    let container = document.getElementById('#textarea-container');
    container.scrollTop = container.scrollHeight;
},
timid laurel
#

#textarea-container is the component you want to scroll on the bottom of, right ?
Or you want to scroll continuously on the bottom of your textarea while streaming content ?

fallen gust
timid laurel
#

Allright

Here's a component I made with the same logic 🙂

<textarea 
  wire:stream="content"
  id="textarea"
  x-data="{
    init: function() {
        const textarea = document.getElementById('textarea');

        function autoResize() {
            if (textarea.value.trim() === '') {
                textarea.style.height = '60px';
            } else {
                textarea.style.height = 'auto';
                textarea.style.height = textarea.scrollHeight + 'px';
            }

            // Scroll to the bottom of the textarea
            textarea.scrollTop = textarea.scrollHeight;
        }

        autoResize();

        const observer = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation) {
                if (mutation.type === 'childList' || mutation.type === 'characterData') {
                    autoResize();
                }
            });
        });

        observer.observe(textarea, {
            characterData: true,
            subtree: true,
            childList: true
        });

        textarea.addEventListener('input', autoResize, false);
    }
  }"
></textarea>
#

Don't forget textarea.scrollTop = textarea.scrollHeight; in the autoResize funcion 😉

fallen gust