Vue+axiosでAjax送信するためのパッケージ「v-api-form」を公開しました!

さてさて、最近は少し忙しくなってしまって以前のように前から書き溜めてたネタを少しずつ記事にするということが実行しにくくなっていますが、その反面色々なパッケージを作ることには時間を割くことはできるようになったので、こちらも少しですがこのブログでお知らせしていきたいと考えています。

そして今回GitHubnpmで公開したパッケージは、Vue+axiosでAjax送信のパラメータを簡単に管理できる「v-api-form」です。

ということで今回は公開したてのv-api-formパッケージの紹介記事を公開します。

※ 開発環境: Vue 2.5
※ 2019/01/10にパッケージを更新し、ファイルの設定方法がnullからFile、もしくはFileListへ変更になりました。

なぜこのパッケージをつくったか

なぜこのパッケージを作ったかというと、もともとVueを使うと変数のバインディングができるので入力ボックスのデータを簡単に取得することはできますが、それは入力に「ファイル選択」を含んでいない場合です。

つまり、ファイル選択が可能なフォームな場合、送信データは(私の場合だと)FormDataを使いますが、いちいち個別にコードを書くのはめんどうだからです。

さらに、以前からもこのブログで紹介しているLaravelバリデーションのエラーメッセージは複数であることを想定しているので、「エラー表示は各入力に対してひとつでいい」場合だといちいちループで最初のものだけ取得するコードを書かないといけないため、これもショートカットできたらと考えました。

インストール

npmコマンドで一気にインストールできます。

npm i v-api-form --save

準備

まずは、メインファイルの/dist/v-api-form.jsを読み込みます。

<script src="/PATH/TO/YOUR/FOLDER/v-api-form/dist/v-api-form.js"></script>

この時点でVueミックスインがすでに読み込まれていて、data変数paramserrorsが使えるようになっています。

そのため、Vueの設定は次のようになります。

new Vue({
el: '#app',
data: {
params: {
email: 'test@example.com',
password: 'passwd',
profile: File, // ファイル選択用(単体)

  photos: FileList, // ファイル選択用(複数)
},

ちなみにパラメータは上から、

  • メールアドレス
  • パスワード
  • プロフィール画像(単体ファイル)
  • その他の写真(複数ファイル)

になります。

次にHTML内にバインディングしていきましょう。

<!-- 通常の入力 -->
<input type="text" v-model="params.email">
<input type="password" v-model="params.password">

<!-- ファイル選択 -->
<input type="file" v-file-model="params.profile">
<input type="file" v-file-model="params.photos" multiple>

この中で上2つは通常通りのバインディングになるので問題はありませんが、下2つはv-api-formパッケージの独自ディレクティブv-file-modelです。

これを設定することでファイルが選択されたら自動的にファイル情報を格納し、さらにここの情報を使って後で紹介するパラメータのクリアなどができるようになっています。

なお、mutipleを使った複数選択にも対応しています。

FormDataを取得する

ではバインディングしたデータを取得してみましょう。
例えば、ボタンをクリックしたらonSubmit()が実行される場合です。

onSubmit() {

const params = this.getFormData();
axios.post('/YOUR/URL', params)
.then((response) => {
// ..
})
.catch((error) => {
// ..
});

}

paramsはデフォルトで設定された変数なのでgetFormData()を呼ぶだけでFormData化されたパラメータを取得することができます。

この中には通常のテキストや英数字などのデータだけでなく、選択されたファイルデータも含まれています。

ちなみにFormDataは直接axiosにパラメータとして使うことができます。

なお、入力とは別のデータを追加したい場合もあると思います。
その場合、FormDataappend()で追加してもいいですが、次のように第1引数で追加パラメータを指定することもできます。

const params = this.getFormData({ _method: 'PUT' });

エラーをセットする

先ほども書きましたが、Laravelが返すエラーメッセージは配列となっているので、最初のものだけを取得するにはループしてそれぞれ取得する必要があります。

これをショートカットするために作られたのがsetFormErrors()です。
やり方は簡単で、axiosが用意してくれているerrorを引数として指定するだけです。

axios.post(url, params)
.then((response) => {
// ..
})
.catch((error) => {
this.setFormErrors(error);
});

これで変数errorsに再構築されたエラーメッセージが格納されるので、this.errors.emailなどとしてエラーメッセージを取得することができるようになります。

ただし、私のようにLaravel + axiosを使っていない場合もあると思います。

その場合はgetFormErrors()new Vue()内で上書きしてください。(errorsetFormErrors()で指定されるデータです)

getFormErrors(error) {

// ここでエラーを準備

return errors;
},

各種データをクリア、リセットする

v-api-formにはパラメータとエラー・データをクリア、もしくはリセットするメソッドがあります。ひとつずつみていきましょう。

パラメータをクリアする

パラメータが全て空白になります。(ただし、ファイル用の変数はFileもしくはFileListになります)

this.clearFormParams();

パラメータをリセットする

上の項目との違いは、データが初期値になるかどうかです。
こちらの場合は、データが初期値に戻ります。

this.resetFormParams();

エラーをクリアする

エラーメッセージを全て空白にします。
そのため、Ajax送信の直前でこのメソッドを呼ぶといいでしょう。

this.clearFormErrors();

複数フォームで使うには

先ほどまでの例ではフォームはページにひとつだけしか存在していませんでしたが、状況によってはフォームが複数ある場合もあることでしょう。

その場合はnew Vue()beforeMountを追加して、setApiFormParams()で各パラメータを指定してください。

beforeMount() {

this.setApiFormParams([
{
params: 'params',
errors: 'errors'
},
{
params: 'customParams',
errors: 'customErrors'
}
]);

}

この例で言うと、変数paramscustomPramsにそれぞれ入力情報が格納され、さらにerrorscustomErrorsにそれぞれのエラーが格納されることになります。

名前を指定してデータを管理する

上記のように複数パラメータを用意した場合、その名前を指定して各メソッドを呼び出すことができます。

名前を指定してFormDataを取得する

第2引数で名前の指定ができます。
この場合は、customParamsに格納されているデータをFormData化して取得することができます。

const params = this.getFormData({}, 'customParams');

名前を指定してエラーをセットする

例えば、customErrorsにエラーを格納したい場合です。
こちらも第2引数へ指定します。

this.setFormErrors(error, 'customParams');

名前を指定してデータをクリア、リセットする

this.clearFormParams('customParams');
this.resetFormParams('customParams');
this.clearFormErrors('customParams');

おわりに

v-api-formは汎用的に使うことを想定していたため、IE 11での動作確認も行っています。

ただ、やはりというかIE対応するためになかなか時間を使わされました(笑)

少し前にedgeが内部をchrome化するというニュースがでましたが、開発者からするとそっちじゃなくてIEの方を優先的にお願いできないでしょうか・・・というのが本音だと思います。

もちろん、過去のソフトウェアが動かなくなるパターンもあるのでしょうが、IEのために生産性が低くなっているのはもはや間違いない事実になっているので・・・こうなったら、みんなで「せいのっ!」で利用をやめませんか(説なる願い ^^;)

ではでは〜!