3

This is an angular app (but anyone with css knowledge can help), where there is a text area with dynamic content.

So as the content item.text changes the text area should grow or shrink according to the content to fit the content perfectly without any overflow.

<textarea [value]="item.text" [placeholder]="item.text ? '' : 'Your Text Here...'" class="font-xl font-bold"></textarea>

// dont worry about the placeholder. you can ignore that.

Currently in my case scrollbar appears & it is not shrinking or growing with the dynamic content.

How can I achieve that?

Or if there is a way to convert a regular html <div> to a textarea, you can suggest that too. But prefers a solution for the above one.

I've tried css rules like, max-content fit-content etc... nothing is working out!

5
  • you can give fix dimension because text area is you increase by mouse pointer. better to give fix dimension Commented Jun 25, 2020 at 13:46
  • can't be done with css alone, needs javascript that can be a little error prone. recommend finding a lib for it instead of rolling your own, angular materials is good: material.angular.io/components/input/… .. if you're open to a lib, I can post usage details Commented Jun 25, 2020 at 13:46
  • I cannot have it fixed. I need it dynamically change height to fit content. That's why I asked for help! Commented Jun 25, 2020 at 13:48
  • @bryan60 hi What module should I import in my NGMODULE in order to use cdktextareaautosize? Commented Jun 25, 2020 at 13:59
  • MatInputModule I added an answer with usage details Commented Jun 25, 2020 at 14:00

5 Answers 5

3

Install npm install ngx-autosize

in html add autosize

<textarea autosize [value]="item.text" [placeholder]="item.text ? '' : 'Your Text Here...'" class="font-xl font-bold"></textarea>

then in appmodule

put in imports: [AutosizeModule ],

Demo

Sign up to request clarification or add additional context in comments.

8 Comments

this won't size to fit a prepopulated value or things pasted or auto filled.... like I said in my comments, this is a buggy area. Use a lib for it.
Are you sure ? In demo When I paste text it again resize height
are you pasting with keyboard commands or your mouse?
@bryan60 hi What module should I import in my NGMODULE in order to use cdktextareaautosize?
This is not getting pasted. This will be automatically populated as the component initializes. Then later if the user wishes to change the content of the textarea he can do that.
|
2

This can't be accomplished with just css, it needs JavaScript that has quite a few corner cases and can be tricky. Such as, pasted input, input populated programatically, auto filled input, handling screen size changes correctly, and on and on, and doing so in a way that is reusable and performs well.

Given all that, I recommend using a lib for this.

I've used angular material's plenty of times with no issues, just add material to your project (can be done via angular CLI with ng add @angular/material) and either import the MatInputModule from @angular/material/input or TextFieldModule from @angular/cdk/text-field (TextFieldModule is quite a bit smaller) to the module where you want to use it, then do:

<textarea cdkTextareaAutoSize cdkAutosizeMinRows="5" [value]="item.text" [placeholder]="item.text ? '' : 'Your Text Here...'" class="font-xl font-bold"></textarea>

you can exclude the cdkAutosizeMinRows option and then it will default to 1 row, but you can use that option to set however many minimum rows you'd like to display. You can also use the cdkAutosizeMaxRows option to make it stop growing at a certain number of rows if you wish, otherwise it will grow indefinitely with the content.

blitz: https://stackblitz.com/edit/angular-4zlkw1?file=src%2Fapp%2Ftext-field-autosize-textarea-example.html

docs: https://material.angular.io/components/input/overview#auto-resizing-textarea-elements

https://material.angular.io/cdk/text-field/overview

7 Comments

If you don't like the aspect, you can remove the "matInput" directive (in this case you can only import the TextFieldModule import {TextFieldModule} from '@angular/cdk/text-field';)
@Eliseo I know the directive used to require the matInput directive, did they remove that requirement when they moved over to cdkTextareaAutosize?
Is a good idea to use this big library for just autosize of textarea? you will install a big library and have to insert its style css into project that may effect project's design. If you don't add css of material then it will not work as expected for example when remove it will not come back to initial. @bryan60
Yep. That's also an issue. Now my app is a bit lagging & also takes more time for compiling.
@pc_coder the size of the entire library isn't very important as it's broken into modules, and use of cdkTextareaAutosize carries no css requirements at all. the TextFieldModule is extremely small at 7KB minified, 24KB otherwise. the MatInputModule is a bit larger, but I can't imagine that use of it or the TextFieldModule has any noticeable impact on performance or build time or bundle size.
|
0

You can't change the height of the textarea without Javascript. But you can use an editable div instead. In plain HTML something like this would serve the same purpose as an textarea and will resize automatically based on the content.

<div class="font-xl font-bold" contentEditable>Hello World</div>

6 Comments

Does this method supports (input) or ([ngModel])?
So that I can get input values if any changes are made to the content by the user?
It would work in jQuery or Vue. I can't speak for Angular as I don't know it very well. But as far as I understand the framework it should work. You can use change or value in plain Javascript so it should work in Angular as well.
@MaZoli contenteditable divs do not implement control value accessor so they don't support ngModel or form controls
Is there a way to attach any custom directive or anything like that so that it turns out to be an input element.
|
0

If you use a <div> which you can edit then it can grow or shrink accordingly.

<div contenteditable="true">This is a div. It is editable. Try to change this text.</p>

2 Comments

Does this method supports (input) or ([ngModel])? Or any formcontrols so that I can receive input values?
You can with javascript or jquery but I am not sure with Angular.
0

The below will loop over the item and compare height to scrollHeight incrementing the height by lineHeight. Then resets the rows once the height is greater than the scroll height

(function () {
  const el = document.querySelector('textarea');
  dynamicallyResize(el);
  el.addEventListener('change', function () { dynamicallyResize(el); });
})();

function dynamicallyResize(el) {
  el == undefined && (el = this.target);
  const lineHeight = 16;
  let i = el.getAttribute('rows'), 
      height = Math.ceil(el.getBoundingClientRect().height);
  el.style.overflow = 'visible'; //triger redraw
  while(height < el.scrollHeight) { 
      height += lineHeight;
      i++; 
      el.setAttribute('rows', i); 
  }
  el.style.overflow = 'auto';
}
<textarea [value]="item.text" [placeholder]="item.text ? '' : 'Your Text Here...'" class="font-xl font-bold" rows="2">Starting text that exceeds the 2 row limit initially placed on this particular text area.</textarea>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.