Auto growing textarea in ionic
Asked Answered
S

9

7

I am trying to add an autogrowing textarea to my app but for some reason it is not working. The module that I am using is https://github.com/tagged/autogrow (it was recommneded on the ionic forum)

Seacock answered 29/6, 2014 at 20:57 Comment(0)
V
11

I wrote a very simple directive that works with Ionic 2 and ion-textarea. Here it is:

import { Directive, HostListener, ElementRef } from "@angular/core";

@Directive({
selector: "ion-textarea[autoresize]" // Attribute selector
})
export class Autoresize {
  @HostListener("input", ["$event.target"])
  onInput(textArea: HTMLTextAreaElement): void {
    this.adjust();
  }

  constructor(public element: ElementRef) {
  }

  ngOnInit(): void {
    this.adjust();
  }

  adjust(): void {
    let ta = this.element.nativeElement.querySelector("textarea");
    ta.style.overflow = "hidden";
    ta.style.height = "auto";
    ta.style.height = ta.scrollHeight + "px";
  }
}

Here is a gist: https://gist.github.com/maxt3r/2485356e91a1969bdb6cf54902e61165

EDIT: Look at the gist for other suggestions from other people.

Varney answered 28/11, 2016 at 17:48 Comment(2)
Works like a charm, but I needed to test if ta exists in adjust() to work. Something like if(ta){ ta.style... }Comity
I also prefer writing your own Directive to npm install --save THIRD-PARTY-NPM-LIBRARY. This way you can fix your own Directive shall something goes wrong in your Directive. Thank you for sharing!Planetoid
G
14

The answer above does not shrink - here is an improved version:

https://codepen.io/benshope/pen/xOPvpm

angular.module('app').directive('expandingTextarea', function () {
    return {
        restrict: 'A',
        controller: function ($scope, $element, $attrs, $timeout) {
            $element.css('min-height', '0');
            $element.css('resize', 'none');
            $element.css('overflow-y', 'hidden');
            setHeight(0);
            $timeout(setHeightToScrollHeight);

            function setHeight(height) {
                $element.css('height', height + 'px');
                $element.css('max-height', height + 'px');
            }

            function setHeightToScrollHeight() {
                setHeight(0);
                var scrollHeight = angular.element($element)[0]
                  .scrollHeight;
                if (scrollHeight !== undefined) {
                    setHeight(scrollHeight);
                }
            }

            $scope.$watch(function () {
                return angular.element($element)[0].value;
            }, setHeightToScrollHeight);
        }
    };
});

This will transform all your textareas to grow/shrink.

Hope that helps!

Gravelly answered 24/3, 2015 at 18:56 Comment(3)
This product an awful effect when the textarea shrink.Excommunicate
I have fixed the bugs and added a codepen demonstrating it :)Gravelly
Beautiful, simple ! Work like a charm ! Thank you :)Daffy
V
11

I wrote a very simple directive that works with Ionic 2 and ion-textarea. Here it is:

import { Directive, HostListener, ElementRef } from "@angular/core";

@Directive({
selector: "ion-textarea[autoresize]" // Attribute selector
})
export class Autoresize {
  @HostListener("input", ["$event.target"])
  onInput(textArea: HTMLTextAreaElement): void {
    this.adjust();
  }

  constructor(public element: ElementRef) {
  }

  ngOnInit(): void {
    this.adjust();
  }

  adjust(): void {
    let ta = this.element.nativeElement.querySelector("textarea");
    ta.style.overflow = "hidden";
    ta.style.height = "auto";
    ta.style.height = ta.scrollHeight + "px";
  }
}

Here is a gist: https://gist.github.com/maxt3r/2485356e91a1969bdb6cf54902e61165

EDIT: Look at the gist for other suggestions from other people.

Varney answered 28/11, 2016 at 17:48 Comment(2)
Works like a charm, but I needed to test if ta exists in adjust() to work. Something like if(ta){ ta.style... }Comity
I also prefer writing your own Directive to npm install --save THIRD-PARTY-NPM-LIBRARY. This way you can fix your own Directive shall something goes wrong in your Directive. Thank you for sharing!Planetoid
S
10

I found a much more better way to do this without using any other third party library or directive.

$scope.updateEditor = function() {
    var element = document.getElementById("page_content");
    element.style.height = element.scrollHeight + "px";
};

Then simply adding ng-keypress="updateEditor()" to the textarea would do the job.

<textarea ng-keypress="updateEditor()" ng-model="bar"> </textarea>

I Hope this helps others who might face this problem in the future.

Update: Here is a codepen for this: http://codepen.io/kpourdeilami/pen/KDepk

Update 2: Use the snippet provided by @benshope

Update 3: If you're on Ionic/Angular 2, use the answer provided by "Max Al Farakh"

Seacock answered 23/7, 2014 at 22:3 Comment(2)
Do not use this! Does not work when you delete the text you just wrote.Stanislaw
Upvoted for your "Update 2" that recommends that we use @benshope's answer. Classy move. Thanks! :)Lucais
D
9

Try Angular-Elastic. It is an angular directive built to auto-expand a textarea. Use bower to install it.

bower install angular-elastic

add it to your project, then you can use it as an attribute

<textarea msd-elastic ng-model="foo"> </textarea>

or as class

<textarea class="msd-elastic" ng-model="bar"> </textarea>
Damian answered 22/7, 2014 at 20:46 Comment(0)
K
7

From Ionic 4.4 it's built-in, see the autoGrow property:

TextArea#Properties

<ion-textarea auto-grow="true" rows="1"></ion-textarea>
Kaoliang answered 2/8, 2019 at 9:30 Comment(2)
This is very simple answer, I don't know Why this answer is at bottom?Perdue
This is the most simple and updated answer, it's working like charm!Alwitt
D
2

Do you mean vertically auto-growing? I tried this:

  <textarea ng-model='doc.description'
   rows='{{doc.description.length/50 + 1}}' 
   cols='50'></textarea>

Kinda hackish, but after having determined an expected column length, lets define the row length based on the length of the inputed text. It starts growing vertically when I start typing! (no scrolling/out of view text).

Derogative answered 13/4, 2015 at 20:20 Comment(1)
If you have new lines, this hack won't work and will scroll text vertically out of view.Eberto
T
2

With ionic-5 , there is an option called auto-grow, set it to true in your view. In css, set min-height, max-height, to control the text grow.

ion-textarea {
min-height: 100px;
max-height: 200px;
}

Also, after the above fix, if you get some odd behaviour with placeholder text, add below inside the ion-textarea

::ng-deep textarea {
min-height: 100px;
}
Tizes answered 4/6, 2020 at 8:37 Comment(0)
E
0

If it can serve someone, I changed a little bit benshope's solution since I needed the textarea to grow even when user do a carriage return.

So instead of listening to the changes on the input value (which didn't always fire when doing a carriage return) I listent the input event on the textarea.

(function () {
'use strict';

angular
        .module('app')
        .directive('expandingTextarea', expandingTextarea);

function expandingTextarea() {
    return {
        restrict: 'A',
        controller: function ($scope, $element, $attrs, $timeout) {
            $element.css('min-height', '0');
            $element.css('resize', 'none');
            $element.css('overflow-y', 'hidden');
            setHeight(0);
            $timeout(setHeightToScrollHeight);

            function setHeight(height) {
                $element.css('height', height + 'px');
                $element.css('max-height', height + 'px');
            }

            function setHeightToScrollHeight() {
                console.log('set height');
                setHeight(0);
                var scrollHeight = angular.element($element)[0]
                        .scrollHeight;
                if (scrollHeight !== undefined) {
                    setHeight(scrollHeight);
                }
            }

            angular.element($element)[0].addEventListener("input", setHeightToScrollHeight);
        }
    };
}})();
Elegy answered 16/2, 2017 at 20:27 Comment(0)
C
0

juste install : bower install angular-elastic or

npm install angular-elastic;

then import the elastic.js file in your index.html like this

    <script src="js/elastic.js" type="text/javascript"></script>

the after that inject it in you angular module like this:

angular.module('yourApp', ['monospaced.elastic']);

the after that in your html file, in your footer-bar do like this:

  <ion-footer-bar  style="height: auto;  overflow: visible !important"><textarea rows="1" msd-elastic  ng-model="myMsg">
</textarea>

Choleric answered 16/3, 2019 at 4:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.