web-dev-qa-db-ja.com

コンテンツに合わせてテキストエリアのサイズを自動変更するにはどうすればよいですか?

textareaのコンテンツのサイズを自動調整しようとしていますが、Enterキーを押して次の行に進んだ後、途方に暮れる問題が発生しています。どうすれば修正できますか?

これは私がやろうとしていることです。下の画像を参照してください。 enter image description here

StackBlitzの例については、こちらをご覧ください link

[〜#〜]コード[〜#〜]

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);
   });
});
4
Joseph

あなたが達成しようとしているのは非常に古いトリックです。私は自分で使用しましたが、別の方法を試しました。

テキスト領域がなぜ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要素を引数として渡す必要があります。

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

1
joyBlanks