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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

1回答

1535閲覧

Laravel+Vue.js3+Inertiaでfilepondを使ったファイルアップロード項目がある編集画面に登録済みのファイルを表示できない

PenelopeG

総合スコア31

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2023/03/01 09:26

実現したいこと

Laravel + Vue.js 3 + Inertia で開発中のお知らせ機能に複数画像アップロードがあります。
登録済みの複数画像をお知らせ編集画面に表示出来ずに困っております。

前提

Laravel、Vue.js3、Inertia いずれも初心者です。

お知らせ投稿の項目は、
・タイトル
・ファイル(複数)
です。(項目は他にもありますが、ここでの質問には不要なので省略しています)

複数ファイルのアップロードに「filepond」ライブラリを使用することにしました。
また、Laravelで使いやすくなると思い、併せて「laravel-filepond」も使用することにしました。

DBは、newsテーブルとimagesテーブル、その中間テーブルがあります。

news --------- id title images --------- id filepath image_news --------- news_id image_id

発生している問題・エラーメッセージ

Create→Storeは成功したのですが、EditでFilepondを適用したInput[type=file]に登録済みの画像をセットすることが出来ずに困っています。

以下の画像のようなイメージです。
(各画像の右上「Upload complete」表示は不要で大丈夫です)
イメージ説明

該当のソースコード

文字数オーバーのため省略部分あります

Create.vue

javascript

1<script setup> 2import { Head, useForm } from '@inertiajs/inertia-vue3'; 3import { onMounted, ref } from "vue"; 4import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout.vue'; 5import ValidationErrors from '@/Components/ValidationErrors.vue'; 6import vueFilePond, { setOptions } from 'vue-filepond'; 7import FilePondPluginFileValidateType from 'filepond-plugin-file-validate-type'; 8import FilePondPluginImagePreview from 'filepond-plugin-image-preview'; 9 10// Import filepond styles 11import 'filepond/dist/filepond.min.css'; 12import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.min.css'; 13 14const props = defineProps({ 15 csrf_token: String 16}) 17 18const filepondImagesInput = ref(null); // Reference the input to clear the files later 19 20const form = useForm({ 21 title: null, 22 images: [], 23}) 24 25const storeNews = () => { 26 form.transform((data) => { 27 return { 28 ...data, 29 images: data.images.map(item => item.serverId) // Pluck only the serverIds 30 } 31 }) 32 form.post(route('news.store'), { 33 forceFormData: true, 34 onSuccess: () => { 35 filepondImagesInput.value.removeFiles(); 36 } 37 }) 38} 39 40// Create FilePond component 41const FilePond = vueFilePond(FilePondPluginFileValidateType, FilePondPluginImagePreview); 42 43// Set global options on filepond init 44const handleFilePondInit = () => { 45 setOptions({ 46 credits: false, 47 server: { 48 url: '/filepond', 49 headers: { 50 'X-CSRF-TOKEN': props.csrf_token, 51 } 52 } 53 }); 54}; 55 56// Set the server id from response 57const handleFilePondImagesProcess = (error, file) => { 58 form.images.push({id: file.id, serverId: file.serverId}); 59}; 60// Remove the server id on file remove 61const handleFilePondImagesRemoveFile = (error, file) => { 62 form.images = form.images.filter(item => item.id !== file.id); 63} 64</script> 65 66<template> 67 <Head title="新規登録" /> 68 69 <AuthenticatedLayout> 70 <template #header> 71 <h2 class="font-bold text-2xl text-stone-800 leading-tight">新規登録</h2> 72 </template> 73 74 <ValidationErrors></ValidationErrors> 75 76 <section class="text-stone-800 body-font relative"> 77 <form @submit.prevent="storeNews" enctype="multipart/form-data"> 78 <div class="pt-10 pb-24"> 79 <div class="flex flex-wrap -m-2"> 80 <div class="p-2 w-full"> 81 <label for="title" class="form-label">タイトル<span class="badge-danger">必須</span></label> 82 <input type="text" id="title" name="title" v-model="form.title" class="w-full form-ctrl"> 83 <p class="form-attention">100文字以内で入力してください</p> 84 </div> 85 <div class="p-2 w-full"> 86 <label class="block form-label">添付ファイル</label> 87 <p class="form-attention">2MB以下のjpg/pngファイルを指定してください</p> 88 <div> 89 <FilePond 90 name="images" 91 ref="filepondImagesInput" 92 class-name="my-pond" 93 allow-multiple="true" 94 accepted-file-types="image/jpeg, image/png" 95 max-files="3" 96 @init="handleFilePondInit" 97 @processfile="handleFilePondImagesProcess" 98 @removefile="handleFilePondImagesRemoveFile" 99 /> 100 </div> 101 </div> 102 <div class="px-2 pt-10 w-full"> 103 <button class="btn-primary">登録</button> 104 </div> 105 </div> 106 </div> 107 </form> 108 </section> 109 110 </AuthenticatedLayout> 111</template>

Edit.vue

javascript

1<script setup> 2// importはCreateと同じため省略 3 4const props = defineProps({ 5 news: Object, 6 images: Array, 7 csrf_token: String 8}) 9 10const filepondImagesInput = ref(null); // Reference the input to clear the files later 11 12const form = useForm({ 13 _method: 'PUT', 14 id: props.news.id, 15 title: props.news.title, 16 images: props.images, 17}) 18 19onMounted(() => { 20 form.images.push(props.images); // ←試しにやってみましたが上手くいかず 21}) 22 23const updateNews = id => { 24 form.transform((data) => { 25 return { 26 ...data, 27 images: data.images.map(item => item.serverId) // Pluck only the serverIds 28 } 29 }) 30 form.post(route('news.update', { news: id }), { 31 forceFormData: true, 32 onSuccess: () => { 33 filepondImagesInput.value.removeFiles(); 34 } 35 }) 36} 37 38// Create FilePond component 39// Createの40行目〜63行目まで同じため省略 40</script> 41 42<template> 43 Createと同じ 44</template>

NewsController.php

php

1<?php 2 3namespace App\Http\Controllers; 4 5use App\Http\Requests\StoreNewsRequest; 6use App\Http\Requests\UpdateNewsRequest; 7use App\Models\News; 8use App\Models\Image; 9use Illuminate\Support\Facades\Auth; 10use Illuminate\Support\Facades\DB; 11use Illuminate\Support\Facades\Storage; 12use Inertia\Inertia; 13use RahulHaque\Filepond\Facades\Filepond; 14 15class NewsController extends Controller 16{ 17 public function index() 18 { 19 // 省略 20 } 21 22 public function create() 23 { 24 return Inertia::render('News/Create'); 25 } 26 27 public function store(StoreNewsRequest $request) 28 { 29 DB::beginTransaction(); 30 31 try { 32 // 添付ファイル 33 $news_images = Filepond::field($request->images)->getFile(); 34 $image_ids = array(); 35 if ( isset($news_images) ) { 36 foreach ( $news_images as $n_img ) { 37 $filepath = $n_img->store('news', 'public'); 38 $img = Image::create([ 39 'title' => $n_img->getClientOriginalName(), 40 'filepath' => $filepath, 41 ]); 42 $image_ids[] = $img->id; 43 } 44 } 45 46 $news = News::create([ 47 'title' => $request->title, 48 ]); 49 50 $news->images()->sync($image_ids); 51 52 DB::commit(); 53 54 return to_route('news.index')->with([ 55 'message' => '登録しました。', 56 'status' => 'success' 57 ]); 58 59 } catch (\Exception $e) { 60 DB::rollBack(); 61 } 62 } 63 64 public function show(News $news) 65 { 66 // 省略 67 } 68 69 public function edit(News $news) 70 { 71 $images = Image::select('id', 'filepath')->orderBy('id')->get(); 72 73 return Inertia::render('News/Edit', [ 74 'news' => $news, 75 'images' => $images, 76 ]); 77 } 78 79 public function update(UpdateNewsRequest $request, News $news) 80 { 81 DB::beginTransaction(); 82 try { 83 $news_images = Filepond::field($request->images)->getFile(); 84 $image_ids = array(); 85 if ( isset($news_images) ) { 86 foreach ( $news_images as $n_img ) { 87 $filepath = $n_img->store('news', 'public'); 88 $img = Image::create([ 89 'title' => $n_img->getClientOriginalName(), 90 'filepath' => $filepath, 91 ]); 92 $image_ids[] = $img->id; 93 } 94 } 95 96 $news->title = $request->title; 97 $news->save(); 98 99 $news->images()->sync($image_ids); 100 101 DB::commit(); 102 103 return to_route('news.index')->with([ 104 'message' => '更新しました。', 105 'status' => 'success' 106 ]); 107 108 } catch (\Exception $e) { 109 DB::rollBack(); 110 } 111 } 112 113 public function destroy(News $news) 114 { 115 // 116 } 117}

試したこと

英語はさっぱりですが、藁にもすがる気持ちで以下のYouTubeをみました。
Laravel Inertia Vue.js - Multiple image upload with FilePond.js
私がやりたいことは、実現は出来るだろうと思いましたが、この動画ではlaravel-filepondが使用されていないのでアプローチが違うと思いました。
laravel-filepondの使用をあきらめた方が早いのでしょうか???

補足情報(FW/ツールのバージョンなど)

Laravel 9
Vue.js 3
Inertia
filepond
laravel-filepond

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

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

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

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

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

guest

回答1

0

自己解決

藁にもすがる気持ちでみた以下のYouTubeを参考にして、当初とは違う方法ですが、やりたかったことは実現できました。
Laravel Inertia Vue.js - Multiple image upload with FilePond.js

投稿2023/04/30 21:52

編集2023/04/30 21:58
PenelopeG

総合スコア31

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問