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

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

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

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

Q&A

解決済

1回答

2469閲覧

Vue3、 vee-validate ボタンをクリックしたときにバリテーションを適用させたい。

tkm0604

総合スコア555

Vue.js

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

0グッド

0クリップ

投稿2022/01/30 06:25

Vue: 3.2.20
vee-validate: 4.5.8
にてフォームに入力された値に対してのバリテーションを作成しました。

それぞれの項目に入力された内容に対してはバリテーションルールを適用できたのですが、

javascript

1 <button @click="saveCanvas('preview')" >アップロード</button>

をクリックしたときにバリテーションを適用させることができません。

全体のコードは下記です。

javascript

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

Formタグに@submitイベントを設定してonSubmit関数を設定。
onSubmit関数の中でサーバへのデータ送信の処理を記述したsaveCanvas('preview')関数を記述。

<button @click="saveCanvas('preview')" >アップロード</button>が発火したときにonSubmit関数からバリテーションルールが適用され、未入力項目があればバリテーションルールが適用されPOST出来ないようにしたいのですが、< button >をクリックすると、各項目undefinedでPOSTされてしまいます。

どうすれば<botton>をクリックしたときにバリテーションが適用されるようにできるでしょうか?

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

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

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

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

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

guest

回答1

0

自己解決

バージョンの違いなど様々な方法があるようなのですが、公式マニュアルをもとに以下のように書いてバリテーション実装できました。

javascript

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

投稿2022/02/03 06:12

tkm0604

総合スコア555

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問