Rails5でBootstrap4のフォームバリデーションを実装してみた(そして思いっきりハマった)
【経緯】
Rails 5 & Bootstrap 4 & turbolinks 5で思いっきりハマったので、メモっときます。
読み込みを早めるためにも、turbolinksは絶対と思っていたので、turbolinksはオフにしない方向で進めました。
思いっきり独学で勉強しているので、何か間違いがあったり、もっとスマートな方法などがあればご教示いただけると幸いです。
【実現したいこと】
・フォームでsubmitボタンを押されたときに、それぞれのフォームに赤枠や緑枠をつける
・エラーがあるとき、メッセージを該当フォームの下に表示する
【環境】
Rails 5.2.3
Bootstrap 4.1.3
tubolinks 5.2.0
devise 4.6.2
Bootstrap(@importの記述 etc.)やdeviseの初期設定は完了しているものとする。
【コード 1】
app/views/devise/registrations/new.html.erb(とりあえずdeviseを例にする)
# フォーム部分のごく一部のみ抜粋 <%= form_for(resource, as: resource_name, url: registration_path(resource_name), :html => {class:"needs-validation", :novalidate => true}) do |f| %> <div class="form-group"> <%= f.label :email %><br /> <%= f.email_field :email, autofocus: true, autocomplete: "email", class:'form-control', required: true %> <div class="invalid-feedback"> メールアドレスを入力してください。 </div> </div> <div class="actions"> <%= f.submit "Sign up" %> </div> <% end %>
【コード 2】
app/assets/javascripts/bootstrap_form.js
(function() { 'use strict'; window.addEventListener('turbolinks:load', function() { // カスタムブートストラップ検証スタイルを適用するすべてのフォームを取得 var forms = document.getElementsByClassName('needs-validation'); // ループして帰順を防ぐ var validation = Array.prototype.filter.call(forms, function(form) { form.addEventListener('submit', function(event) { if (form.checkValidity() === false) { event.preventDefault(); event.stopPropagation(); } form.classList.add('was-validated'); }, false); }); }, false); })();
【必要と思われること】
・formに「needs-validation」クラスを付与する
・formに「novalidate」のブール値属性を付与する
・読み込ませるjavascriptの「window.addEventListener」の引数として、’load’ではなく、’turbo links:load’を用いる。
・フォームに「:required :true」などバリデーションをかけたい要素を付与する
【雑記】
半日ほど悩んだ末、答えにたどり着きました笑
RailsでJavascriptやstylesheetで色々制御してたらturbolinksが悪さをするって昔からよく話題になってますが、うまく付き合いたいものです。
bootstrapの公式サイトには”load”を引数としてとっている例しか記載がないので(当たり前)、URL直打ちしたらきちんと動くのに、リンクたどったり、ブラウザの戻るボタンとかでは全く動かない、1回目のsubmitは反応せず、2回目は赤枠だけ表示されてエラーメッセージが出ないなど、泥沼でしたw
冒頭にも記載しましたが、完全独学で学んでいるため、間違っている箇所、スマートじゃない箇所があればご指摘いただけると幸いです。
ディスカッション
コメント一覧
まだ、コメントがありません