この記事の対象者
- JavaScriptをRailsに組み込んでみたい方
- CRUD処理は理解されている方
- 細かい説明が欲しい方
*最終コードは最後に書いております。説明が必要ない方は「最終的なコード」をご覧ください。
今回作成するもの
今回作成するものは、画像のように「xxx/xxx文字」と残り文字数を伝えるものになります
今回の想定外
- 文字の色を変更すること
- 文字数を超えて入力できること
- CSSによる見た目の修正
準備すること
- フォームの作成
(サンプル)
<%= form_with model: @モデル名, local: true do |f| %>
<%= f.text_area :content %>
<% end %>
*この記事では、alert
で動作確認を行う記述があります。
確認できましたら、alert
は削除ください。
目次
- JSファイルを作成
- 文字数を取得する
- viewに表示させる
- 関数の作成
1.JSファイルを作成
まずは、JSファイルを作成します。名前は任意で構いません。
今回はcountLength
とします。
touch app/javascript/packs/countLength.js
+ document.addEventListener('turbolinks:load', () => {
+ alert('動作確認'); //確認用です。
+ })
次に、このファイルを読み込みます
import "./countLength"
alertが表示されればOKです!(確認後は削除してくだい。)
これで、JSファイルの準備ができました!
2.文字数を取得する
次に、文字数を取得しましょう。
今回取得する必要がある文字数は、以下の3つです
- 最大文字数
- 現在入力している文字数
- 残り文字数
この3つを算出する必要があります。
1つずつ確認していきましょう。
1.最大文字数
**「フォームで入力できる最大文字数」**を取得します。
最大文字数は、自分でフォームに設定する必要があります
id
とmaxlength
(最大文字数)を付与しましょう
例
<%= f.text_area :content %>
↓
<%= f.text_area :content, id: "textarea", maxlength:"1000" %>
これで、最大1000文字までしか打てないように制限がかかりました。
実際に1000文字以上打てるか確認してください。
このmaxlength: 1000
をJSファイル(countLength.js
)で取得していきます。
以下のコードを追加してください。
document.addEventListener('turbolinks:load', () => {
+ let textarea = document.getElementById('textarea'); //テキストエリアを取得
+ let maxLength = textarea.maxLength; //最大の文字数を取得
+ alert(maxLength); //確認用
})
maxLength
が表示されればOKです。
まずは、最大文字数を取得することができるようになりました。
2.現在入力している文字数
次に、現在入力している文字数を取得します。
先ほど定義した変数textarea
を用いて、textarea.value.length
で取得できます。
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ファイルで実行しましょう!
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_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側に渡すことができます。
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}文字`; //残りの文字/最大文字数を出力
})
これで、残り文字を出力することができます
以上で完成になりま・・・せん!
これでは、ページが表示された時の情報が入るため、後から入力しても数字が変わりません。
なので、関数を作成して、入力したら文字数が反映される仕様にします。
4.関数の作成
まず、どのような条件と動作になるか言語化しておきます
言語化
「id="textarea"
を持つテキストエリア」に文字を入力した時、「入力し終わった直後の残り文字を算出して、表示させる」
という風に置き換えることができます。
それでは、条件を満たす時に実行される関数を作成します。
テキストエリアに文字を入力された時に動作するイベントとして、今回'keyup'というイベントを使用します。
//テキストエリアに文字をkeyupしたときに動作する関数を作成
textarea.addEventListener('keyup', function(){
//ここに動作を書いていきます。
})
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です!
これで、関数が動作する条件を設定することができました。
最後に中身を作成します
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)があるたびに、残り文字数を表示する関数を実装できました!
動作確認してみてください!
最終的なコード
<%= form_with model: @モデル名, local: true do |f| %>
<%= f.text_area :content, id: "textarea", maxlength:"1000" %>
<div id="message"></div>
<% end %>
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')
で値を取得できた場合のみ、動作するように条件分岐させております。(最終的なコードに追加してあります。)
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}文字`
})
+ }
})