やりたいこと
フォーム内容をコントローラに送信する前に、「データの成形」「バリデーション」をしたい。
やれるようになること
- ビューをリロードすることなく、エラーメッセージを表示できる
- フォームのデータを成形して、フォームの入力内容以外の情報をもコントローラに渡せる
概要
- フォームの送信ボタン(id="submit_btn"とします)が押される
- JSのイベントが発火
- フォーム送信を止める
- JSでデータを操作
- JSで本送信
コード概要
概要でできることは
- フォームの送信の止め方
- コントローラに渡す情報の追加方法
- バリデーション
- エラーメッセージの表示
フォームはニックネーム入力欄のみと仮定します
= form_for @user, html: {id: 'submit__btn'} do |f| = f.text_field :nickname, class: "nickname_input" #error #エラーメッセージ表示場所 #add_info #JSでのデータ追加場所
//送信ボタンがクリックされた時にイベントが発火する $('#submit_btn').on('click', function(e){ e.preventDefault(); //フォーム送信を止める var nicknameLength = $('.nickname_input').val().length //ニックネームの文字数を取得 //取得した文字数を値にもつ、見えないinputタグを生成する $("#add_info").append( $('<input type="hidden" name="nickname_length">').val(nicknameLength) ); //ニックネームが入力されているかをバリデーション if (nicknameLength >= 1 ) { $('#submit_btn').submit(); //入力されている場合本送信 } else { //入力されていない場合、エラーメッセージを作成 var errorHtml = `<ul id= 'upload-error'> <li>ニックネームを入力してください</li> </ul>` $('#upload-error').remove(); //すでに表示しているエラーメッセージがある場合削除 $('#error').append(errorHtml); //エラーメッセージをビューに追加 $('html,body').scrollTop(0); //ページのトップへスクロール } });
1. フォームの送信の止め方
まずは、送信ボタンがクリックされた時にイベントを発火させます。
続いて、以下の記述でフォームの送信をストップします。
e.preventDefault();
2. コントローラに渡す情報の追加方法
フォームの情報を元に、新たなデータをinputタグを用いて追加します。
typeを"hidden"にすることでビューには表示されませんが、コントローラではparams[:nickname_length]としてこのタグの情報を取得できます。
$("#add_info").append( $('<input type="hidden" name="nickname_length">').val(nicknameLength) );
3. バリデーション
フォームの情報を元に、入力されているかを確認します。
入力されている場合は、本送信を行います。
if (nicknameLength >= 1 ) { $('#submit_btn').submit(); //本送信 } else {
4. エラーメッセージの表示
バリデーションに引っかかった場合、エラーメッセージを作成し、ビューに追加します。この場合は、本送信は行いません。
var errorHtml = `<ul id= 'upload-error'> <li>ニックネームを入力してください</li> </ul>` $('#upload-error').remove(); //すでに表示しているエラーメッセージがある場合削除 $('#error').append(errorHtml); //エラーメッセージをビューに追加 $('html,body').scrollTop(0); //ページのトップへスクロール
まとめ
JSでのデータ成形・バリデーションができれば、ビュー上でユーザーが操作した情報を元に新たなデータを作成・送信できたり、バリデーションもページリロードなしでできるので、入力内容・選択内容がリセットされずUXも向上するかと思います。
今回は、本当に簡単な例で紹介させていただきましたが、いくらでも応用可能かと思いますので、色々試してみてくださいね。