Laravel 6 で Bootstrap File Input を使う(Font Awesome 5 のインストールも)
Bootstrap 4 の <input type="file">
にプレビューの機能などを追加していい感じにしてくれる Bootstrap File Input を Laravel 6(というか、Laravel Mix)で使うのに、割と悪戦苦闘したので、まとめておきます。
Bootstrap File Input の説明ページにも書いてありますが、Bootstrap 4 には Glyphicons が同梱されていないので、デフォルトの状態だとアイコンが表示されません。Bootstrap File Input には Font Awesome 5 に対応したテーマも同梱されているので、Font Awesome 5 もあわせてインストールします。
Bootstrap File Input と Font Awesome 5 のインストールには、npm を利用します。
npm install bootstrap-fileinput --save
npm install @fortawesome/fontawesome-free --save
次に、これを Laravel Mix で Laravel から使えるように設定していきます。まず、resources/js/bootstrap.js
に以下の内容を追記します。
window._ = require('lodash')
try {
window.Popper = require('popper.js').default
window.$ = window.jQuery = require('jquery')
// 以下を追記
require('bootstrap')
require('bootstrap-fileinput')
require('bootstrap-fileinput/themes/fas/theme.min')
require('bootstrap-fileinput/js/locales/ja')
} catch (e) {}
bootstrap-fileinput/themes/fas/theme.min
が Font Awesome 5 用のテーマ、bootstrap-fileinput/js/locales/ja
は日本語の言語設定です。
次に、resources/sass/app.scss
を編集します。
@import '~bootstrap/scss/bootstrap';
@import '~bootstrap-fileinput/scss/fileinput';
@import '~@fortawesome/fontawesome-free/scss/solid';
@import '~@fortawesome/fontawesome-free/scss/fontawesome';
ここで割とハマっていたのですが、@import '~@fortawesome/fontawesome-free/scss/fontawesome';
だけでは Font Awesome 5 は有効になりません。fontawesome.scss
を見てみるとわかるのですが、fontawesome.scss
(とそこから import される sass)には、@font-face
や font-family
の設定が入っていないのです。bootstrap-fileinput/themes/fas/theme.min
では、fas クラスを使っているので、~@fortawesome/fontawesome-free/scss/solid
をあわせてインポートする必要があります。
その後、以下を実行してアセットのコンパイルを行います。
npm run production
Laravel Mix を利用した Font Awesome 5 のインストールについて検索していると、webpack.mix.js
に
.copy(
'node_modules/@fortawesome/fontawesome-free/webfonts',
'public/webfonts'
)
を追加するように書かれているものが割と見つかりますが、追記しなくても Laravel Mix がコンパイル時にファイルのコピーもしてくれるので、必要ありません。
あとは、Blade の中でこんな感じで使います。
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap File Input のテスト</title>
<!-- Scripts -->
<script src="{{ mix('/js/app.js') }}" defer></script>
<!-- Styles -->
<link href="{{ mix('/css/app.css') }}" rel="stylesheet">
</head>
<body>
<form method="POST" action="{{ route('user.update', [$user->id]) }}" enctype="multipart/form-data">
@method('PUT')
@csrf
<div class="form-group row">
<label for="images" class="col-md-3 col-form-label text-md-right">画像</label>
<div class="col-md-7">
<div class="custom-file">
<input type="file" class="custom-file-input" id="images" name="images[]" multiple>
<label class="custom-file-label" for="images">ファイルを選択してください(複数可)</label>
</div>
<input id="images" name="images[]" type="file" class="file" multiple
data-show-upload="false" data-show-caption="true" data-msg-placeholder="ファイルを選択してください(複数可)"
data-browse-on-zone-click="true">
</div>
</div>
</form>
<script type="module">
$('#images').fileinput({
theme: 'fas',
language: 'ja',
})
</script>
</body>
</html>
設定できるオプションは Bootstrap File Input のサイトを確認してほしいのですが、もう一つハマったのは、<script type="module">
の部分。<script>
のままだと、ReferenceError: $ is not defined
のエラーが出て動きません。
原因は、<script src="{{ mix('/js/app.js') }}" defer>
の部分で、defer
の指定がされているため。<script>
のままだと、jQuery が読み込まれる前にインラインスクリプトが実行されてしまうのです。
このあたりについては、インラインscript(ララジャパン)で詳しく説明されているので、そちらをご覧ください。
ディスカッション
コメント一覧
まだ、コメントがありません