簡體   English   中英

如何自動調整文本區域的大小以適應內容?

[英]How to auto resize the textarea to fit the content?

我正在嘗試自動調整textarea的大小以使其適合其中的內容,但是在單擊 Enter 進入下一行后,我遇到了口吃問題。 我怎樣才能解決這個問題?

這就是我想要做的,見下圖。 在此處輸入圖像描述

請參閱此鏈接以獲取 StackBlitz 示例

代碼

this.form.valueChanges.subscribe(() => {
   const textarea = this.myDiv.nativeElement;
   textarea.addEventListener('keydown', function() {
       setTimeout(() => {
           this.style.cssText = 'height:auto; padding:0';
           this.style.cssText = 'height:' + this.scrollHeight + 'px';
       }, 0);
   });
});

這里的addEventListener是多余的,因為valueChanges已經在字段更改時通知您。 相反,使用ViewChild引用myDiv更新高度。

this.myForm.valueChanges.subscribe(value => {
    this.myDiv.nativeElement.style.height = 'auto';
    this.myDiv.nativeElement.style.height = `${this.myDiv.nativeElement.scrollHeight}px`;
});

然后將overflow: hidden添加到您的 css 中,這樣滾動條就不會顯示。

textarea {
    resize: horizontal;
    overflow: hidden;
}

您可以保持resize: horizontal; 但不再需要它,因為 textarea 無論如何都會自動調整大小。

這是StackBlitz上的一個工作示例。

您要達到的目標是一個非常古老的技巧。 我自己使用過它,但嘗試了不同的方法。

更有意義的是,為什么文本區域會跳動,因為您每次擊鍵時都將height = 0計算為滾動高度,以便您可以分配新的高度。

我計算了 fontSize 或 lineHeight 並計算了行數和基於此調整的初始高度。 因此,在每次擊鍵時,您只需分配高度而不使文本區域高度 = 0

textareaProps = null;
getHeight(element) {
  const lines = element.value.split(/\r\n|\r|\n/).length;
  if(!this.textareaProps) {
    const autoStyle = getComputedStyle(element);
    const lineHeight = parseInt(autoStyle.lineHeight);
    const adjust = parseInt(autoStyle.height) - lineHeight;
    this.textareaProps = {adjust, lineHeight}
  }
  const { adjust, lineHeight } = this.textareaProps;
  const height = lines * lineHeight + adjust;
  return height + 'px';
}

您現在需要調用此方法來獲取高度並將 textarea 元素作為 arg 傳遞。

element.style.cssText = 'height:' + getHeight(element) ;

編輯 2

遺憾的是,上述解決方案僅在用戶有換行符時才有效。 當您輸入一個大行文本區域時,它會換行,但不會增加高度。 因此引入了一個代理 html 元素,它將具有與文本區域值相同的文本,並將提供我們可以分配給我們的文本區域的高度。

textareaProps = null;
getHeight(element) {
  if(!this.textareaProps) {
    const proxy = document.createElement('div');
    const {padding, width, fontSize, height, lineHeight} = getComputedStyle(element);
    const css = [
      'position:absolute',
      'visibility: hidden',
      'pointer-events:none',
      `width: ${width}`,
      `padding:${padding}`,
      `min-height: ${height}`,
      `font-size:${fontSize}`,
      `line-height:${lineHeight}`,
    ].join(';');
    proxy.style.cssText=css;
    this.textareaProps = {
      proxy: document.body.appendChild(proxy), 
      adjust: (parseInt(fontSize))
    };
  }
  const { proxy, adjust} = this.textareaProps;
  proxy.innerText = element.value + '.';
  return (proxy.offsetHeight + adjust) + 'px';
}

更新了 StackBlitz https://stackblitz.com/edit/next-line-view-child-ssnp4q

對於幾乎在 2021 年仍在尋找答案的任何人,這里的官方 Angular 材料文檔對此進行了介紹。 通過nativeElement直接操作 DOM 是一種反模式。

<mat-form-field [style.fontSize]="fontSize.value">
  <mat-label>Autosize textarea</mat-label>
  <textarea matInput
            cdkTextareaAutosize
            #autosize="cdkTextareaAutosize"
            cdkAutosizeMinRows="1"
            cdkAutosizeMaxRows="5"></textarea>
</mat-form-field>

如果您不想要插件,有一個非常簡單的解決方案

$(document).ready(function() {
     $('textarea').on('keyup keypress', function() {
        $(this).height(0);
        $(this).height(this.scrollHeight);
    }); 
    
    $("textarea").each(function(textarea) {
         $(this).height(0);
        $(this).height(this.scrollHeight);
    });

});
<textarea rows="15" id="code" disabled placeholder="Description"></textarea>

rows="15" 將最小高度設置為 15 行

el = document.getElementById("code");
el.style.height = "auto";
// code to populate textarea
el.style.height = (5 + el.scrollHeight) + "px";

這幫助我根據其中填充的內容將 textarea 設置為高度。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM