StephenW
StephenW

Reputation: 183

How to set scrollHeight in textarea that autogrows?

I am building a todo list and have two text areas. The first textarea is where user adds todo item. It works and auto grows on event input. The second textarea is where the todo items are displayed and does not display properly. On edit input event the text is fully shown, but for some reason on event blur (when user clicks on page) the text is not fully shown. Should display like first textarea. Here is a visual example of the problem. Full codepen here

Note: Source I tried implementing for both textareas.

    const createTodoText = (todo) => {
    const itemText = document.createElement('TEXTAREA');
    itemText.setAttribute('id', 'display-text');
    itemText.classList.add('todoText');
    itemText.addEventListener('input', function () {
        var scroll_height = itemText.scrollHeight;
        itemText.style.height = scroll_height + 'px';
    });
    itemText.value = todo.name;
    // itemText.rows = itemText.value.length / itemText.cols;
    //update todo item when user clicks away
    itemText.addEventListener('blur', (e) => {
        todo.name = e.currentTarget.value;
        renderTodos();
    });
    return itemText;
};

Upvotes: 1

Views: 3311

Answers (3)

Amir Makram
Amir Makram

Reputation: 12988

First of all, you need to remove renderTodos(), which is the cause for you the problem.

If you want to get the remain on size of the textbox at its creation, you should at this couple of lines before the input eventlistener in the createTodoText() function

  var scroll_height = input.scrollHeight + 25; 
  itemText.style.height = scroll_height + 'px';

Upvotes: 0

Caleb Hillary
Caleb Hillary

Reputation: 743

You are rendering the whole page on each edit right? This is not exactly a good approach. You can just render(update DOM) for the modified data.

But for the current problem, the issue is that the height of textarea is not updated in the render function. It just renders the default height instead of taking the content into account.

So, you can apply the function that you apply on input, inside renderTodo

const renderTodos = (todo) => {
    ul.innerHTML = '';
    todos.forEach((item) => {
        let li = document.createElement('LI');
        li.setAttribute('class', 'item');
        li.setAttribute('data-key', item.id);
        const itemText = createTodoText(item);
        const cb = buildCheckbox(item);
        const db = buildDeleteButton(item);
        li.append(cb);
        li.append(db);
        li.append(itemText);
        ul.append(li);

        // Update the height of textarea
        let scroll_height = itemText.scrollHeight;
        itemText.style.height = scroll_height + 'px';
    });
};

Note that I have updated height after appending to DOM. This is because scrollheight is a property that is related to the DOM, and needs to be obtained after you append the element to DOM.

Hope this clarifies your query.

Upvotes: 1

CODERWAL JI
CODERWAL JI

Reputation: 3

The problem you're facing is that, the box resizes only on input event, and outside it the stylesheet resizes it to default, you need to check you css once. :>

Upvotes: 0

Related Questions