1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Rails+JavaScript】残り文字を表示させる[コピペOK]

Last updated at Posted at 2021-04-30

この記事の対象者

  • JavaScriptをRailsに組み込んでみたい方
  • CRUD処理は理解されている方
  • 細かい説明が欲しい方

*最終コードは最後に書いております。説明が必要ない方は「最終的なコード」をご覧ください。

今回作成するもの

今回作成するものは、画像のように「xxx/xxx文字」と残り文字数を伝えるものになります

スクリーンショット 2021-04-30 16 01 20

今回の想定外

  • 文字の色を変更すること
  • 文字数を超えて入力できること
  • CSSによる見た目の修正

準備すること

  • フォームの作成
    (サンプル)
_form.html.erb
<%= form_with model: @モデル名, local: true do |f| %>
  <%= f.text_area :content %>
<% end %>

*この記事では、alertで動作確認を行う記述があります。
確認できましたら、alertは削除ください。

目次

  1. JSファイルを作成
  2. 文字数を取得する
  3. viewに表示させる
  4. 関数の作成

1.JSファイルを作成

まずは、JSファイルを作成します。名前は任意で構いません。

今回はcountLengthとします。

ターミナル
touch app/javascript/packs/countLength.js
app/javascript/packs/countLength.js
+ document.addEventListener('turbolinks:load', () => {
+   alert('動作確認'); //確認用です。
+ })

次に、このファイルを読み込みます

application.js
import "./countLength"

alertが表示されればOKです!(確認後は削除してくだい。)
これで、JSファイルの準備ができました!

2.文字数を取得する

次に、文字数を取得しましょう。

今回取得する必要がある文字数は、以下の3つです

  • 最大文字数
  • 現在入力している文字数
  • 残り文字数

この3つを算出する必要があります。

1つずつ確認していきましょう。

1.最大文字数

**「フォームで入力できる最大文字数」**を取得します。

最大文字数は、自分でフォームに設定する必要があります

idmaxlength(最大文字数)を付与しましょう

_form.html.erb
<%= f.text_area :content %><%= f.text_area :content, id: "textarea", maxlength:"1000" %>

これで、最大1000文字までしか打てないように制限がかかりました。
実際に1000文字以上打てるか確認してください。

このmaxlength: 1000をJSファイル(countLength.js)で取得していきます。

以下のコードを追加してください。

app/javascript/packs/countLength.js
document.addEventListener('turbolinks:load', () => {

+ let textarea = document.getElementById('textarea'); //テキストエリアを取得
+ let maxLength = textarea.maxLength; //最大の文字数を取得
+  alert(maxLength); //確認用

})

maxLengthが表示されればOKです。

まずは、最大文字数を取得することができるようになりました。

2.現在入力している文字数

次に、現在入力している文字数を取得します。
先ほど定義した変数textareaを用いて、textarea.value.lengthで取得できます。

app/javascript/packs/countLength.js
document.addEventListener('turbolinks:load', () => {
  let textarea = document.getElementById('textarea');
  let maxLength = textarea.maxLength;
+ let currentLength = textarea.value.length; //テキストエリアに入力されている文字数を取得
+ alert(currentLength);//確認用

})

currentLengthが表示されればOKです。(formにいくつか文字を入力しておくとわかりやすいです。)

これで、現在入力している文字数を取得できました。

3.残り文字数を取得

最後に、**残り何文字打てるか?**を取得します。

残り文字数は、言葉にすると以下のようになります。

残り文字数 = 最大文字数 - 現在入力している文字数

これを実際にJSファイルで実行しましょう!

app/javascript/packs/countLength.js
document.addEventListener('turbolinks:load', () => {
  let textarea = document.getElementById('textarea');
  let maxLength = textarea.maxLength;
  let currentLength = textarea.value.length;

+ remainingLength = maxLength - currentLength //残り文字 = 最大文字数 - 現在入力している文字数
+ alert(remainingLength); //確認用
})

remainingLengthが表示されればOKです。

これで、必要な3つの要素をJSファイルで取得することができました。

3.viewに表示させる

最後に、取得した文字数を表示させましょう!
まずは文字数を表示させるdivタグを作成し、id="message"を付与します。

_form.html.erb

<%= form_with model: @モデル名, local: true do |f| %>
  <%= f.text_area :content, id: "textarea", maxlength:"1000" %>

+ <div id="message"></div>

<% end %>

そして、先ほど取得した最大文字数残りの文字数<div id="message"></div>に反映させます。

JavaScriptでinnnerHTMLメソッドというメソッドを使用することで、値をview側に渡すことができます。

app/javascript/packs/countLength.js
document.addEventListener('turbolinks:load', () => {
  let textarea = document.getElementById('textarea');
  let maxLength = textarea.maxLength;
  let currentLength = textarea.value.length;
  remainingLength = maxLength - currentLength;

+ let message = document.getElementById('message'); //メッセージを表示する要素を取得
+ message.innerHTML = `${remainingLength}/${maxLength}文字`; //残りの文字/最大文字数を出力

})

これで、残り文字を出力することができます

以上で完成になりま・・・せん!

スクリーンショット 2021-04-30 16 01 20のコピー2

これでは、ページが表示された時の情報が入るため、後から入力しても数字が変わりません。
なので、関数を作成して、入力したら文字数が反映される仕様にします。

4.関数の作成

まず、どのような条件と動作になるか言語化しておきます

言語化
id="textarea"を持つテキストエリア」に文字を入力した時、「入力し終わった直後の残り文字を算出して、表示させる」

という風に置き換えることができます。

それでは、条件を満たす時に実行される関数を作成します。

テキストエリアに文字を入力された時に動作するイベントとして、今回'keyup'というイベントを使用します。

app/javascript/packs/countLength.js
   //テキストエリアに文字をkeyupしたときに動作する関数を作成
    textarea.addEventListener('keyup', function(){
      //ここに動作を書いていきます。  
    })  
app/javascript/packs/countLength.js
document.addEventListener('turbolinks:load', () => {
  let textarea = document.getElementById('textarea');
  let maxLength = textarea.maxLength;
  let currentLength = textarea.value.length;
  remainingLength = maxLength - currentLength;
  let message = document.getElementById('message');
  message.innerHTML = `${remainingLength}/${maxLength}文字`;

  //テキストエリアでkeyupイベントが発生した時に動作する関数を作成。  
+ textarea.addEventListener('keyup', function(){
+   alert('動作確認');
+ }) 

})

キーUPするたびにアラートが表示されればOKです!
これで、関数が動作する条件を設定することができました。

最後に中身を作成します

app/javascript/packs/countLength.js
document.addEventListener('turbolinks:load', () => {
  let textarea = document.getElementById('textarea');
  let maxLength = textarea.maxLength;
  let currentLength = textarea.value.length;
  remainingLength = maxLength - currentLength;
  let message = document.getElementById('message');
  message.innerHTML = `${remainingLength}/${maxLength}文字`;

  textarea.addEventListener('keyup', function(){

    //現在の文字数を再取得する
+   let currentLength = textarea.value.length
    //現在の文字数を再出力する
+   message.innerHTML = `${maxLength - currentLength }/${maxLength}文字`
   }) 
})

これで、入力(keyup)があるたびに、残り文字数を表示する関数を実装できました!
スクリーンショット 2021-04-30 16 01 20

動作確認してみてください!

最終的なコード

_form.html.erb
<%= form_with model: @モデル名, local: true do |f| %>
  <%= f.text_area :content, id: "textarea", maxlength:"1000" %>
  <div id="message"></div>
<% end %>
app/javascript/packs/countLength.js
document.addEventListener('turbolinks:load', () => {
  if (document.getElementById('textarea') !==  null) { 
    let textarea = document.getElementById('textarea');
    let maxLength = textarea.maxLength;
    let currentLength = textarea.value.length;
-   remainingLength = maxLength - currentLength; //リファクタリング
    let message = document.getElementById('message');
+   message.innerHTML = `${maxLength - currentLength}/${maxLength}文字`; //改善

    textarea.addEventListener('keyup', function(){
      let currentLength = textarea.value.length
      message.innerHTML = `${maxLength - currentLength}/${maxLength}文字`
   }) 
  }
})

今後

今後、以下を実装してみたいと思っています。追加できるようになれば、この記事に追加しようと思います。

  • <div id = "message"></div>をJSファイルで作成する(view側で設定する必要をなくす)
  • 残り文字数が少なくなった時、色を変化させる

エラー対応

上記に説明がありませんが、document.getElementById('textarea')を取得できない場合、エラーが発生することがわかりました。

そのため、document.getElementById('textarea')で値を取得できた場合のみ、動作するように条件分岐させております。(最終的なコードに追加してあります。)

app/javascript/packs/countLength.js
document.addEventListener('turbolinks:load', () => {
+ if (document.getElementById('textarea') !==  null) { 
    let textarea = document.getElementById('textarea');
    let maxLength = textarea.maxLength;
    let currentLength = textarea.value.length;
    let message = document.getElementById('message');
    message.innerHTML = `${maxLength - currentLength}/${maxLength}文字`;

    textarea.addEventListener('keyup', function(){
      let currentLength = textarea.value.length
      message.innerHTML = `${maxLength - currentLength}/${maxLength}文字`
   }) 
+ }
})
1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?