LoginSignup
0
0

file_fieldのデザインを変更する

Last updated at Posted at 2024-05-11

きっかけ

file_fieldのデザインをデフォルトのものから変更したいと思いましたが、
UIkitでは単数のfile_fieldのclassは用意されているものの、
複数用のfile_fieldは用意されていなかったので、
自分で変更する方法を調べて変更してみました。

初学者のため、誤りがありましたらご指導いただけると幸いです。

環境

Rails7.1
UIkit
ActiveStorage
stimulus

前提として
すでにmodelやdb等は作成してあるとして進めさせていただきます。

完成系のイメージ

送信ボタンにはUIkitのデザインをあててます。
スクリーンショット 2024-05-11 14.06.24.png

file選択ボタンの部分をデフォルトから
スクリーンショット 2024-05-11 14.08.53.png
少しUIkitのデザインに寄せた感じにします。

実装

要点としては、下記になります。

  1. file_fielddisplay: none;を設定する (class: 'hidden'で設定)
  2. file_fieldlabelで囲み、labelclassでcssをあてる
  3. file_fieldに表示したい文字はlabelfile_fieldの間に記載する
new.html.erb
<%= form_with(model: @photo, url: photos_path, local: true) do |f| %>

  <label class='file_field'>
    <span class="ml-5">画像を選択する</span>
    <%= f.file_field :images, multiple: true, class: 'hidden'%>
  </label>
  <div class='uk-margin'>
    <%= f.submit '保存', class: 'uk-button uk-button-default' %>
  </div>
<% end %>

file_fieldのボタンの中に表示する文字はspanで囲った部分になっています。

参考にさせていただいたサイトでは、file_fieldclass: 'hidden'を設定すると
デフォルトのデザインは消えるとあったのですが、
私の場合Tailwindを使用していなかったから?か消えなかったため、cssにhiddenを設定します。

また、新しく充てたいデザインはclass='file_field'としてcssに記載しています。

photo.scss
.hidden {
  display: none !important;
}

.file_field {
  background-color: rgb(253, 253, 253);
  border: 1px solid #ced4da;
  border-radius: 0.25rem;
  padding: 0.75rem 1rem;
}
.file_field:hover {
  border-color: #80858b;
}

display: noneだけでも消えたのですが、もし消えないようなら!importantもつけてみてください
!importantをつけるとスタイルの宣言の優先度を上げて適用されます。

file_fieldhoverについては、UIkitでの送信ボタンの方にデザインを寄せた感じです。

javascriptで選択したfile数を表示する

上記の設定までで完成系のイメージのボタンにはなり、送信もできますが、
このままだとファイルを選択した後も「画像を選択する」が表示されていて、
ユーザーが本当に選択されたのか?と戸惑ってしまいます。

file_fieldアイコン内の文字を選択した数を表示できるようにします。

スクリーンショット 2024-05-11 14.56.46.png

追加する部分

  1. 選択された画像数を取得するjsをphoto_contoroller.jsで定義する
  2. photo_controller.jslabel部分で適用する
  3. new.html.erbspanfile_fieldにjsで定義したtargetを記載する
photo_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ["fileField", "fileLabel"]

  connect() {
    this.fileFieldTarget.addEventListener('change', this.updateFileLabel.bind(this));
  }

  disconnect() {
    this.fileFieldTarget.removeEventListener('change', this.updateFileLabel.bind(this));
  }

  updateFileLabel() {
    let selectedFileCount = this.fileFieldTarget.files.length;
    this.fileLabelTarget.textContent = selectedFileCount + " 個の画像を選択しています";
  }
}

fileFieldtargetをhtmlのformのfile_fieldに設定し、file_fieldでファイルが選択されたら、
chengeイベントが発生し、updateFileLabel()が実行されます。

updateFileLabel()では、選択されたファイル数(length)を取得して、表示する文字を組み、fileLabelをtargetで設定したhtmlの部分の文字が変更されます。

new.html.erb
<%= form_with(model: @photo, url: photos_path, local: true) do |f| %>

  <%# 変更箇所 data-controller='photo'とすることでphoto_controller.jsの内容が使える %>
  <label class='file_field' data-controller='photo'>
    <%# 変更箇所 表示文字を変える部分にfileLabel targetを設定 %>
    <%# 画像を選択する  の部分はデフォルトとして表示される %>
    <span class='ml-5' data-photo-target='fileLabel'>画像を選択する</span>
    <%# 変更箇所 ファイル数のchangeをチェックする部分にfileField targetを設定 %>
    <%= f.file_field :images, multiple: true, class: 'hidden', data: { photo_target: 'fileField' } %>
  </label>
  <div class='uk-margin'>
    <%= f.submit '保存', class: 'uk-button uk-button-default' %>
  </div>
<% end %>

デザイン変更の手順は以上となります。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0