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

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

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

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

Laravel 6

Laravel 6は、オープンソースなPHPのフレームワーク。Webアプリケーションの開発に適しており、バージョン6はLTSです。5.8での向上に加えて、セマンティックバージョニングの採用やLaravel Vaporとのコンパチビリティなどが変更されています。

Q&A

解決済

1回答

1661閲覧

Vue3 formで作成した画像データの取得、POSTができない。

tkm0604

総合スコア552

Vue.js

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

Laravel 6

Laravel 6は、オープンソースなPHPのフレームワーク。Webアプリケーションの開発に適しており、バージョン6はLTSです。5.8での向上に加えて、セマンティックバージョニングの採用やLaravel Vaporとのコンパチビリティなどが変更されています。

0グッド

0クリップ

投稿2022/05/25 07:39

[実現したいこと]
Vue3コンポーネントでFormを作成。form内のcanvas、title、commentをaxios 経由でLaravel DBへPOST

[問題点]
フォームを投稿すると、laravelからcanvasの値がnullのため、エラー(Call to a member function hashName() on null)

vue.js

1<template> 2 <v-form method="POST" @submit="onSubmit" enctype="multipart/form-data"> 3 <div> 4 <!-- 画像エリア --> 5 <div id="image_area"> 6 <canvas class="h-80 mx-auto my-2" ref="preview" id="preview"></canvas> 7 <input 8 type="file" 9 name="image" 10 accept="image/*" 11 ref="selectImage" 12 @change="previewImage" 13 /> 14 </div> 15 <v-field 16 name="text" 17 v-model="text" 18 type="text" 19 id="canvas_text" 20 :rules="textRequired" 21 ></v-field> 22 <button 23 id="drawText" 24 type="button" 25 @click="drawText('preview', 'canvas_text')" 26 >文字を描く 27 </button> 28 <p class="text-danger"><error-message name="text"></error-message></p> 29 <!-- タイトル入力 --> 30 <div> 31 <v-field 32 id="title" 33 v-model="title" 34 type="text" 35 name="title" 36 placeholder="タイトル" 37 :rules="titleRequired" 38 ></v-field> 39 <p class="text-danger"><error-message name="title"></error-message></p> 40 </div> 41 <!-- コメント入力エリア --> 42 <div> 43 <v-field 44 id="comment" 45 as="textarea" 46 v-model="comment" 47 name="comment" 48 cols="30" 49 rows="10" 50 placeholder="コメント入力" 51 :rules="commentRequired" 52 ></v-field> 53 <p class="text-danger"> 54 <error-message name="comment"></error-message> 55 </p> 56 </div> 57 <button id="saveCanvas" @click="saveCanvas('preview');twitterShare()"> 58 <i class="fab fa-twitter">Twitter</i> 59 </button> 60 </div> 61 </v-form> 62</template> 63<script> 64import * as VeeValidate from "vee-validate"; 65import { Form, Field, ErrorMessage } from "vee-validate"; 66import { ref, selectImage, preview } from "vue"; 67 68export default { 69 components: { 70 ErrorMessage: VeeValidate.ErrorMessage, 71 }, 72 73 74 setup() { 75 //////////canvasの画像をinput type="file"にプレビュー////////// 76 const selectImage = ref(); 77 const preview = ref(); 78 let previewImage = () => { 79 let file = selectImage.value.files; //ファイル情報の取得 80 console.log(file); 81 const canvas = preview.value; //canvasタグ 82 const fileReader = new FileReader(); 83 console.log(file); 84 fileReader.onload = function () { 85 const ctx = canvas.getContext("2d"); 86 const image = new Image(); 87 image.src = fileReader.result; 88 image.onload = function () { 89 canvas.width = image.width; 90 canvas.height = image.height; 91 ctx.drawImage(image, 0, 0); 92 }; 93 }; 94 fileReader.readAsDataURL(file[0]); 95 }; 96 97 //////////キャンバスに文字を描く////////// 98 let drawText = (canvas_id, text_id) => { 99 const canvas = preview.value; 100 const ctx = canvas.getContext("2d"); 101 const text = document.getElementById(text_id); 102 //文字のスタイルを指定 103 ctx.font = "32px serif"; 104 ctx.fillStyle = "#404040"; 105 //文字の配置を指定(左上基準にしたければtop/leftだが、文字の中心座標を指定するのでcenter 106 ctx.textBaseline = "center"; 107 ctx.textAlign = "center"; 108 //座標を指定して文字を描く(座標は画像の中心に) 109 const x = canvas.width / 2; 110 const y = canvas.height / 2; 111 ctx.fillText(text.value, x, y); 112 }; 113 114 //////////Canvasのデータをblob化/title/commentをaxiosでPOST////////// 115 let saveCanvas = (canvas_id) => { 116 const type = "image/png"; 117 const canvas = document.getElementById(canvas_id); 118 const dataurl = canvas.toDataURL("image/jpeg", 0.85); 119 const bin = atob(dataurl.split(",")[1]); 120 const buffer = new Uint8Array(bin.length); 121 for (let i = 0; i < bin.length; i++) { 122 buffer[i] = bin.charCodeAt(i); 123 } 124 125 const blob = new Blob([buffer.buffer], { type: type }); 126 127 //new FormData() を作成 128 const data = new FormData(); 129 data.append("canvas", blob, "image.png"); 130 data.append("title", title.value); 131 data.append("comment", comment.value); 132 133 axios 134 .post("/api/images", data,{ 135 headers: { 'content-type': 'multipart/form-data' } 136 }) 137 .then((res) => { 138 console.log("success"); 139 }) 140 .catch((error) => { 141 new Error(error); 142 }); 143 }; 144 145 return { 146 text: "", 147 title: "", 148 comment: "", 149 previewImage, 150 selectImage, 151 preview, 152 drawText, 153 saveCanvas, 154 }; 155 }, 156 }, 157}; 158</script>

上記コード <div id="image_area">の内容を取得、POSTできればいいのか?
と考えているのですが、<script>内で
//////////canvasの画像をinput type="file"にプレビュー//////////
//////////キャンバスに文字を描く//////////
//////////Canvasのデータをblob化/title/commentをaxiosでPOST//////////
のそれぞれのメソッドで処理はそれぞれ書いていて、comment, titleはLaravelに渡されています。

なぜ、canvasだけnullになってしまうのでしょうか?

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

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

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

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

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

guest

回答1

0

自己解決

以下の様にformタグの中にaxiosからPOSTの処理を書いたvueコンポーネント埋め込んでいた事でPOSTが2回リクエストされている。1回目はPOSTに情報が入っているからDBにも保存処理されていたが、2回目のPOSTは何も情報が入っていないから、Laeavel側で全ての値がnull、status500のエラーが出ていました。

blade.php

1 <form method="POST" action="{{route('images.store')}}" enctype="multipart/form-data"> 2 @csrf 3 <image-component></image-component> 4 </form>

投稿2022/05/29 06:53

tkm0604

総合スコア552

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問