#制作環境
Windows 10
Laravel : 6.18.35
Laravel/ui : 1.0
Laravel-mix : 5.0.1
Bootstrap : 4.0.0
jQuery : 3.2
XAMPP
PHP : 7.4.3
Visual Studio Code
#はじめに
この記事はプログラミングをはじめたばかりの素人が、できたことをメモするのに利用しています。
内容には誤りがあるかもしれません。
あくまでデザインとファイル名の表示が目的のため、実際に送信(POST)できるようにはしてません。
最低限必要だと思う内容しか記載していないので、バリデーション等も直接必要ではないので割愛してます。
#はじめる前に
Laravelをインストールしておいて下さい。
Laravel-mixを使用することを前提にしています。
Bootstrap 4がインストールされていない方は、まずインストールを行ってください。
インストールにはnpmを利用するので、Node.jsのインストールが先に必要です。
Node.jsをインストールしていない場合は、下記よりダウンロードして先にインストールをお願いいたします。
Node.js
http://nodejs.org/
#Bootstrap 4のインストール
Laravelのスカフォールドを利用します。
※以降のやり方はLaravelのバージョンによって、使用するコマンド等が違います。
Laravelのリファレンスに沿ってインストールをお願いいたします。
Laravelのプロジェクトのディレクトリでターミナルを起動し、以下を実行する。
composer require laravel/ui:^1.0 --dev
次に、以下を実行。
php artisan ui bootstrap
次に、以下を実行。
npm run install
最後に以下を実行。
npm run dev
リファレンス
https://readouble.com/laravel/6.x/ja/frontend.html
#ビューの作成
ベースとなるビューを作成します。
resources>views 内に新しくinputfile.blade.phpを作成します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>ファイル選択</title>
</head>
<body>
<h1>input file</h1>
<form>
<label>画像選択 <input type="file" name="img" accept=".png,.jpg,.jpeg,image/png,image/jpg"></label>
</form>
</body>
</html>
実際に送信するのであれば、<form>
にaction
やenctype="multipart/form-data
を記述しないといけませんが、今回は見た目だけに重点を置いているので記述はしません。
#ルーティングの作成
今回送信や登録は行わないので、コントローラは使用しません。
指定のアドレスにアクセスされたら、viewを直接返すようにします。
routes 内のweb.phpを開き以下のように記述します。
Route::get('/inputfile', function () {
return view('inputfile');
});
#現状のデザイン
/inputfile
にアクセスすると
画像選択の画面のみが表示されます。
ファイルを選択すると、
「選択されていません」の部分にファイル名が表示されます。
このデザインをBootstrap 4を使い変更します。
#webpack.mix.jsの編集
webpack.mix.jsを開き内容を以下に変更します。
変更前
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css');
変更後
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css')
.version();
この記事の目的からすると、この記述はなくても全然いいのですが、laravel-mixの内容を見てもらうためにあえて触れてます。
この記述がなくても、今後の操作に影響はありません。
Laravel-mixですが、すごい大雑把に言うと特定の場所に置かれたJavaScriptファイルやcssファイル・Font AwesomeやBootstrap等をまとめて記述できるようにしてくれるものです。
※素人のイメージなので間違ってるかもしれませんが、そんなには遠くないと思いますwww。
使い方は次のビューの編集でやります。
##記述の内容①
mix.js('resources/js/app.js', 'public/js')
上記は、resources>js
内にあるapp.js
をpublic/js
ディレクトリに出力するという意味です。
出力されると、public/js
内に同じ名前のapp.js
ファイルが作成されます。
resources>js
内にあるapp.js
に必要なファイルを読み込むよう記述すると、1つにまとめて出力(トランスパイル)してくれます。
現在同じディレクトリにはbootstrap.js
しかないので、app.js
を開くと先頭には
require('./bootstrap');
しかありませんが、ここに追記するだけで、自身で作成したjsファイルもまとめて出力してくれます。
ファイル名を表示するJavaScript(jQuery)を作成する時は、このLaravel-mixを使用します。
【注意事項】
内容を変更した時は必ずターミナルで以下を実行してください。
npm run dev
都度やるのが面倒な場合は、
npm run watch-poll
これで変更があれば自動で更新してくれます。
##記述の内容②
.sass('resources/sass/app.scss', 'public/css')
これも内容は一緒でcssに関するものをまとめて出力してます。
また、その過程でsass等新しい記述のcssを古いcssの記述に変換してくれてます。
記述の内容③
.version();
これはキャッシュに残った古いJavaScriptを読み込ませないようにするための記述です。
これを記述するとidパラメーターが都度採番されます。
#ビューの編集
ビューに以下を追記します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- Bootstrap ここから追記 -->
<link href="{{ mix('css/app.css') }}" rel="stylesheet">
<!-- ここまで追記 -->
<title>ファイル選択</title>
</head>
<body>
<h1>input file</h1>
<form>
<label>画像選択 <input type="file" name="img" accept=".png,.jpg,.jpeg,image/png,image/jpg"></label>
</form>
<!-- Bootstrap JavaScript ここから追記 -->
<script src="{{ mix('js/app.js') }}"></script>
<!-- ここまで追記 -->
</body>
</html>
2箇所追記してます。
この記述で、先ほどまとめたcssファイルやjsファイルを読み込んでいます。
cssは<head>
の中に記述し、jsは<body>
の終了タグの直前に記述します。
この状態で/inputfile
にアクセスすると、フォントなどの見た目が少しかわるはずです。
#デザインの変更①
Bootstrapで見た目を変更してみます。
<form>
の中を以下のように変更してみてください。
<form>
<div class="form-group">
<label for="img">画像選択</label>
<input type="file" class="form-control-file" id="img" name="img" accept=".png,.jpg,.jpeg,image/png,image/jpg">
</div>
</form>
見ての通り、これだとHTML標準のものとあまり変わりません。
Bootstrap 4 リファレンス
https://getbootstrap.jp/docs/4.3/components/forms/
#デザインの変更② カスタムファイル
カスタムファイルを使用して、もう少しBootstrapらしいデザインにしたいと思います。
<form>
の中を以下のように変更してみてください。
<form>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroupFileAddon">画像選択</span>
</div>
<div class="custom-file col-3">
<input type="file" class="custom-file-input" id="inputGroupFile" name="img" accept=".png,.jpg,.jpeg,image/png,image/jpg" aria-describedby="inputGroupFileAddon">
<label class="custom-file-label" for="inputGroupFile" data-browse="参照">ファイルを選択</label>
</div>
</div>
</form>
このままだと左上の端に表示され見にくいので、以下を更に追記します。
<body>
<div class="container">
<h1 class=" pt-5">input file</h1>
<!-- 省略 -->
</div>
<!-- Bootstrap JavaScript -->
<script src="{{ mix('js/app.js') }}"></script>
</body>
現状のデザインを確認してみてください。
見た目はよくなりましたが、実際にファイルを選択しても、デザインを変更する前のようにファイル名が表示されません。
これでは選択されたかどうかがわかりづらいので、ファイル名が表示されるようにします。
#スクリプトの作成
resources>js
内に新しくinputfile.js
を作成します。
作成したら、同じディレクトリにあるapp.js
を開き、require('./bootstrap');
の下に以下のように追記します。
require('./inputfile');
#JavaScriptで記述
ファイル名の表示を行うスクリプトを、JavaScriptで作成します。
先ほど作成した、inputfile.js
を開き以下のように記述してください。
// id="inputGroupFile"の要素の内容を取得し その要素でchangeイベントが発生したら関数を実行する
document.getElementById("inputGroupFile").addEventListener("change", function() {
// 選択されたファイルの最初のファイルのデータを変数fileに代入する
let file = this.files[0];
// class="custom-file-label"の要素の内容を取得し その内容の最初のオブジェクトの文章をfile.nameで書き替える
document.getElementsByClassName("custom-file-label")[0].innerHTML = file.name;
}, false);
filesで取得できる値
- name (ファイル名)
- size (Bytes)
- type (MIME Type)
##files[0]の記述について
input type="file"
は同時に複数のファイルをアップロードすることが可能なため、値を取り出す時には何番目にアップロードしたものか指定しないといけません。
今回の場合は1つしかアップできないので、最初のファイルを指定するため[0]を記述する。
※最初は[0]で2つ目が[1]になるので注意!
##getElementsByClassName()で取得できる要素の内容について
files
と同じく、getElementsByClassName
でもgetElementsByClassName("custom-file-label")[0]
で[0]を指定してます。
理由は取得される要素の内容が、配列ではなくオブジェクト型だからです。
idと違い、classは同じ名前を何回でも使用できます。
そのため、複数の要素の内容が入るようにオブジェクト型になっています。
なので、innerHTMLで文章を変更する時は、何番目のオブジェクトの文章なのかを指定してあげないといけません。
この[0]が抜けるとうまくいきませんので気をつけてください。
#スクリプトをまとめる
inputfile.js
の保存が完了したら、ターミナルを起動し以下を実行します。
npm run dev または npm run watch-poll
操作が完了したら、/inputfile
にアクセスして動作を確認してください。
上のように選択した画像ファイルの名前が表示されたらOKです。
ちなみにinputで指定してるので、pngかjpegしか選択できません。
#jQueryで記述
せっかくなので、jQueryで同じ記述を書いてみます。
やってることは一緒です。
JavaScriptの記述はコメントアウトするか、削除してください。
inputfile.js
を開き以下のように記述してください。
$(function() {
$('#inputGroupFile').on('change', function() {
let file = $(this).prop('files')[0];
$('.custom-file-label').text(file.name);
});
});
jQueryの方がすっきりしてますね。
保存したら忘れず、ターミナルで
npm run dev または npm run watch-poll
を実行してください。
操作が完了したら、/inputfile
にアクセスして動作を確認してください。
同じようにファイル名が表示されていればOKです。