0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Vue.js,Railsで画像プレビュー機能を作成

Posted at

##完成図
スクリーンショット 2021-06-14 22.03.07.png

参考:https://blog.capilano-fw.com/?p=1189

##やりたい事
ユーザーのプロフィール編集機能を作成するにあたって
・プロフィール画像を画像を選択したらそれを即時に反映させる
・デフォルトのラジオボタンはデザインがダサいのでカスタマイズする
・アクセスした時点ではでは既に設定されているアイコンを表示する

###全体コード

edit.html.erb(一部)

<div class="field">
 <%= f.label :image, "プロフィール画像" %><br />
  <div id="img_field" @change="onFileChange($event)">
   <img :src="imageData" v-if="imageData" class="edit-preview-image">
   <img src=<%= current_user.image %> v-else class="edit-preview-image">
   <label for="file-input" class="input-file-button">
    ファイルを選択
   </label>
  <%= f.file_field :image, id: "file-input", accept: "image/*" %>
 </div>
</div>
image_upload_vue.js

import Vue from 'vue/dist/vue.esm'
import App from '../app.vue'

document.addEventListener('DOMContentLoaded', () => {
  const app = new Vue({
    el: '#img_field',
    data: {
      imageData: ''
    },
    methods: {
      onFileChange(e) {
  
        const files = e.target.files;

        if(files.length > 0) {
    
            const file = files[0];
            const reader = new FileReader();
            reader.onload = (e) => {
    
                this.imageData = e.target.result;
    
            };
            reader.readAsDataURL(file);
        }
      }
    },
    components: { App }
  })
})

###デフォルトのラジオボタンをカスタマイズする

edit.html.erb

<label for="file-input" class="input-file-button">
  ファイルを選択
</label>
<%= f.file_field :image, id: "file-input", accept: "image/*" %>
application.scss

#img_field > input
{
    display: none;
}

.input-file-button {
  cursor: pointer;
  background: #636;
  color: white;
  padding: 5px 10px;
  border-radius: 5px;
  width: 100%;
  text-align: center;
}

デフォルトのラジオボタンはidを付与してdisplay:none;で非表示にし、それに対応するlabelタグにcssを当てる事でオリジナルのボタンを作成できる

###v-ifを使って画像プレビュー機能を作成

edit.html.erb

<div id="img_field" @change="onFileChange($event)">
   <img :src="imageData" v-if="imageData" class="edit-preview-image">
   <img src=<%= current_user.image %> v-else class="edit-preview-image">
・・・

application.scss
.edit-preview-image {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  border: 1px solid #eee;
  // 縦横比を変えないままトリミング
  object-fit: cover;
  display: block;
  margin: 10px auto;
}

imageDataに値が挿入されていれば上のimgタグ(新しく選択した画像)が表示され画像を選択していない場合はしたのimgタグ(現在設定しているアイコン)が表示される

思っていたよりもrails✖︎vueの記事が無かったので苦戦しました(SPA作る系のやつならたくさんあったのですが)
でもVue.jsの学習の一環としてこの機能はVueで実装してみたかったので粘った甲斐があったと思います。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?