質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Bootstrap

BootstrapはウェブサイトデザインやUIのWebアプリケーションを素早く 作成する可能なCSSフレームワークです。 Twitter風のデザインを作成することができます。

Q&A

解決済

1回答

4536閲覧

Bootstrapのmodalが正常に動作しない Rails6 + webpacker環境 "modal is not a function..."

naokit-dev

総合スコア424

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Bootstrap

BootstrapはウェブサイトデザインやUIのWebアプリケーションを素早く 作成する可能なCSSフレームワークです。 Twitter風のデザインを作成することができます。

0グッド

0クリップ

投稿2020/07/21 16:10

編集2020/07/23 05:13

環境

Ruby 2.7.1, Rails 6.0.3, PostgreSQL 11
webpacker 5.1.1
Bootstrap 4.5.0, jQuery 3.5.1 (gemを使用せずwebpackerにてインストール)
Docker上のローカル環境

Bootstrapのスタイルは正常に適応されている状態です

問題

BootstrapのModalが正常に動作しない
(CDNからBootstrapをインストールすると正常に動作する)

CDNインストールでお茶を濁しておりましたが、
プロダクション環境では問題ないものの、デプロイ環境ではjQueryがBootstrapよりも先に読み込まれていない旨のエラーが出ており、
根本解決が必要かと思い質問を挙げさせていただきました。

検証

プロダクション環境、modalの動作が期待される場面で
Chromeのコンソールで確認すると

Uncaught TypeError: $(...).modal is not a function...

そこで<head>タグ内に以下のように記述し、
CDNからインポートを試みるとmodalは正常に動作するようになります。
(jQueryとStylesheetのCDNインポートは不要でした)

html

1 <head> 2 ... 3 <%= stylesheet_pack_tag "application", media: "all", "data-turbolinks-track": "reload" %> 4 <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track": "reload" %> 5 <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> 6 <!-- font awesome --> 7 <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css" 8 integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ" crossorigin="anonymous"> 9 <!-- Bootstrap --> 10 <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" 11 integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"> 12 </script> 13 </head>

このことから

  • ビューに記載されたスクリプトは適切
  • modalのclass, id記述も問題ない

かと考えています。

また上記<head>内で
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
よりも上の行でBootstrapをCDNからのインポートすると、
同様にChromeのコンソールにて、jQueryに依存しているから先にインストールしてくれとのエラーが生じます

このことからwebpackerでのjQueryのインストールまではうまくいっており

  • Bootstrapのインストールがうまく行ってない
  • jQuery > Bootstrapの順で呼び出されていない

といった原因なのかと推察しているのですが、
これ以上検証、解決のすべが思い浮かばず質問させていただきました。

長文、お手数ですが後学のためアドバイスをお願いいたします。

ソース

config/webpack/environment.js

javascript

1const { 2 environment 3} = require('@rails/webpacker') 4 5const webpack = require('webpack') 6 7environment.plugins.prepend('Provide', 8 new webpack.ProvidePlugin({ 9 $: 'jquery', 10 jQuery: 'jquery', 11 Popper: ['popper.js', 'default'] 12 }) 13) 14 15module.exports = environment

app/javascript/packs/application.js

javascript

1// This file is automatically compiled by Webpack, along with any other files 2// present in this directory. You're encouraged to place your actual application logic in 3// a relevant structure within app/javascript and only use these pack files to reference 4// that code so it'll be compiled. 5 6require("@rails/ujs").start() 7require("turbolinks").start() 8require("@rails/activestorage").start() 9require("channels") 10require("@fortawesome/fontawesome-free") 11 12import 'bootstrap' 13import 'bootstrap/dist/js/bootstrap'; 14import './bootstrap_custom.js' 15import '../stylesheets/application' 16 17 18 19// Uncomment to copy all static images under ../images to the output folder and reference 20// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>) 21// or the `imagePath` JavaScript helper below. 22// 23// const images = require.context('../images', true) 24// const imagePath = (name) => images(name, true)

importの内容は重複していますが、
それぞれ個別に試してもエラーは解消されませんでした

また、以下のサイトを参考に、
import 'bootstrap/js/dist/modalを含むbootstrap_custom.jsを作成し
Bootstrapのjavascriptを明示的にimportしてみたのですが
これもうまくいかず

How to install bootstrap 4.3 on a Rails 6 app using Webpack | by Guilherme Pejon | Medium

app/javascript/packs/bootstrap_custom.js

javascript

1import 'bootstrap/js/dist/alert' 2import 'bootstrap/js/dist/button' 3import 'bootstrap/js/dist/carousel' 4import 'bootstrap/js/dist/collapse' 5import 'bootstrap/js/dist/dropdown' 6import 'bootstrap/js/dist/index' 7import 'bootstrap/js/dist/modal' 8import 'bootstrap/js/dist/popover' 9import 'bootstrap/js/dist/scrollspy' 10import 'bootstrap/js/dist/tab' 11import 'bootstrap/js/dist/toast' 12import 'bootstrap/js/dist/tooltip' 13import 'bootstrap/js/dist/util'

package.json

json

1{ 2 "name": "myapp", 3 "private": true, 4 "dependencies": { 5 "@fortawesome/fontawesome-free": "^5.13.1", 6 "@rails/actioncable": "^6.0.0", 7 "@rails/activestorage": "^6.0.0", 8 "@rails/ujs": "^6.0.0", 9 "@rails/webpacker": "5.1.1", 10 "bootstrap": "4.5.0", 11 "clipboard": "^2.0.6", 12 "jquery": "^3.5.1", 13 "popper.js": "^1.16.1", 14 "turbolinks": "^5.2.0" 15 }, 16 "version": "0.1.0", 17 "devDependencies": { 18 "webpack-dev-server": "^3.11.0" 19 } 20}

ビュー(.erb)

html

1<script> 2 $(window).on('load', function () { 3 $('#modal_initial').modal(); 4 }); 5</script> 6 7<div class="modal fade" id="modal_initial" tabindex="-1" role="dialog" aria-labelledby="modal_initialCenterTitle" 8 aria-hidden="true" data-backdrop="static"> 9 ... 10</div>

$('#modal_initial').modal();の部分を$('#modal_initial').show();$('#modal_initial.modal').show();とするとよいなどのアドバイスも海外サイトで見られましたが、いずれも駄目でした

追記

デプロイ環境でのみ、jQueryがないと言われるエラーについては
以下のように変更することで解消しました

config/webpack/environment.js

javascript

1const { 2 environment 3} = require('@rails/webpacker') 4 5const webpack = require('webpack') 6 7#以下'jquery'から'jquery/src/jquery'に変更 8environment.plugins.prepend('Provide', 9 new webpack.ProvidePlugin({ 10 $: 'jquery/src/jquery', 11 jQuery: 'jquery/src/jquery', 12 Popper: ['popper.js', 'default'] 13 }) 14) 15 16module.exports = environment

現状の問題点は

  • webpackerで管理しているBootstrapのスタイルは適応されるが、特定のjavascriptが動かない
  • <head>内でCDNからBootstrapをインストールすると、前述のjavascriptが動く

対症的解決法はあるのですが、後学のため根本解決のためのアドバイスを引き続きお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

jQuery → Bootstrap → jQueryとjQueryが2回読み込まれBootstrapのメソッドがキャンセルされている可能性が高いかと思います。

なので、まずは該当ページで検証ツールを利用して<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>以外で、jQueryを読み込んでいないか確認することからはじめると切り分けがしやすいかと思います。


#追記:解決方法はわかったのですが、なぜそうなるのかがわかりません。おわかりになる方がいらっしゃればコメントなどで教えていただけると助かります。

前提:
jQueryを2回読み込んでいない。

解決方法:
・erbに直接記載せず、application.jsなどに記載してjavascript_pack_tagから読み込む
・もしturbolinksを利用しているのならaddEventListenerを追加

JavaScript

1//application.js 2 3require("@rails/ujs").start() 4require("turbolinks").start() 5require("@rails/activestorage").start() 6require("channels") 7require("@fortawesome/fontawesome-free") 8 9import 'bootstrap' 10import '../stylesheets/application' 11 12document.addEventListener("turbolinks:load", function(){ 13 $(window).on('load', function () { 14 $('#modal_initial').modal(); 15 }); 16})

投稿2020/07/21 23:36

編集2020/07/23 04:40
no1knows

総合スコア3365

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

naokit-dev

2020/07/22 01:34

no1knows様 ご指摘どおり、過去の投稿等では、 `app/javascript/packs/application.js`内でjQueryが複数requireされていたという 内容が散見され、その辺りが問題かと推察しております。 解答ありがとうございます "jQueryを読み込んでいないか確認"の具体的な方法がわからず、 以下の投稿を参考にしてみました [HTML - jqueryの読み込みができているか確認する方法|teratail](https://teratail.com/questions/196429) ```javascript <script> $(function(){ // if document is ready alert('jQuery is ready.') }); </script> ``` のコードを<head>内に仕込んだところ、 一度だけアラートが表示されます また `<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>`をコメントアウトすると `$ is not defined`とエラーが表示され、$をjqueryに置き換えても同様です。 jQueryはwebpacker以外から読み込まれていない、ということかと思いますがいかがでしょうか? webpack内での重複読み出しについて検証する方法がありましたらご教授いただけますと幸いです。 引き続き自分でも検証方法を調べてみたいと思います。
naokit-dev

2020/07/22 01:41

回答へのコメントはMarkdown表記に対応していないのですね、 見づらい内容で申し訳ございません。
no1knows

2020/07/22 01:59

上記の方法なら<%= javascript_packをコメントアウトして、JavaScriptのalertを</body>の直前において実行してみてはいかがでしょうか? それでhead以外にjQueryが読み込まれていないか切り分けができると思います。
naokit-dev

2020/07/22 02:04

no1knows様 同様の検証を行って見たところ `$ is not defined`とエラーが表示され、$をjqueryに置き換えても同様です。
no1knows

2020/07/22 04:59

ソースを見せてもらうことはできますか? 適切な回答ができるかどうかは、見てみないとなんとも言えないのですが・・・
naokit-dev

2020/07/22 12:50

ありがとうございます せっかくなので見ていただきたいのですが、 レポジトリごとで良かったでしょうか? https://github.com/naokit1030/myapp.git 独学で初アプリのため、他にもお気づきの点があれば教えていただけると幸いです。 よろしくお願いいたします。
no1knows

2020/07/23 00:10

headにvue.jsの記載があるのでVueを利用しているという理解で良いでしょうか? Vueは使ったことがないのですが、もしそうであれば、そもそもBootstrapの設定方法が違うようです。 https://qiita.com/masa08/items/3474d97a1283dfc275c9
naokit-dev

2020/07/23 01:52

お時間をいただきありがとうございます。 提示頂いた記事拝見いたしました。 Vueは別のスクリプトで利用しており、CDNでインストールしています。 BootstrapはRails上のwebpackerで管理しているイメージで、 yarnでインストールしwebpackでバンドルしている状態だと思っております。 [Rails 6: the missing developer setup guide - DEV](https://dev.to/vvo/a-rails-6-setup-guide-for-2019-and-2020-hf5) コメントを踏まえ、Head内のVueインストールの部分を消して見ましたが、 状況は変わらず - Bootstrapのスタイルは適応される - Bootstrapのjavascriptが利用できない"modal is not a function..."
no1knows

2020/07/23 04:41

エラーがでる原因がわからずに申し訳ないです。。。
naokit-dev

2020/07/23 05:26

とんでもないです また、回答内容の変更ありがとうございます。 turbolinksの部分試してみます。
naokit-dev

2020/07/29 05:06

引き続き対応いただきありがとうございます。 取り急ぎ、上記記事を参考に対応してみましたが、 やはりmodalのみ同様のエラーが出ております。 また状況を整理して、補足を書いてみたいと思います。
no1knows

2020/07/29 07:42

naoki_tさん、ご対応ありがとうございます。 こちらでももう少し情報収集してみたいと思います。
no1knows

2020/07/29 08:30 編集

こちらで新しいプロジェクトを作って確認してみました。 Bootstrap、jQuery導入 Qiita: https://qiita.com/shungo_m/items/53bcae18a740495d1eb3 Application.jsに下記コードを追加 window.jQuery = window.$ = require('jquery') 上記でmodalのエラー(Uncaught TypeError: $(...).modal is not a function...)が消えました。 rails g scaffold test name:textでtestページを作成 testのindex.html.erbにbootstrap公式のモーダルコード(LiveDemo)をコピペ https://getbootstrap.jp/docs/4.2/components/modal/ Turbolinksはひとまずおいて、下記コードを追加 <script> $(window).on('load', function () { $('#exampleModal').modal('show'); }); </script> ページを立ち上げるとエラーもなく、モーダルが表示された状態になります。 一度テストアプリで動作確認してから、現状のコードを確認すると良いと思います
naokit-dev

2020/07/29 14:31 編集

no1knowsさん 動作確認できました 解決までフォローいただきありがとうございました。 おかげさまで新しい学びがあり、スッキリいたしました。 また機会があればよろしくお願いいたします。
no1knows

2020/07/29 16:18

naoki_tさん、拙い解答でお手数をおかけしました。 僕も勉強になりました。ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問