2019/07/03

『Vue.js + Ajax + Laravel で作成する TO DOリストの作成』の続きです。
前回は削除機能を追加しました。
TO DO リスト 削除機能 (Vue.js + Ajax + Laravel)
今回は編集機能についてエントリーします。
なお、今回で『Vue.js + Ajax + Laravel で作成する TO DOリスト』のシリーズは最終回になります。

デモサイト
【ベーシック認証】id:laraweb / pass: laraweb
なお、以前に Vue.js でTO DOリストを作成しました。
今回のソースはこれをベースに作成しています。
事前に見ていただくと、今回の説明はわかりやすいかもしれません。
手順
Laravel ( Blade )
ソースコード
    <!--ループ処理-->
    <ul class="list-group">
        <li class="list-group-item" v-for="(todo, index) in list">
            @{{ todo.task }}
            <span class="pull-right">
                <button class="btn btn-xs btn-info" v-on:click="edit(index);">
                    <span class="glyphicon glyphicon-pencil"></span>
                </button>
                <button class="btn btn-xs btn-warning" v-on:click="remove(todo.created_at,index);"> <!--todo.id は undefined になる-->
                    <span class="glyphicon glyphicon-trash"></span>
                </button>
            </span>
        </li>
    </ul>
解説
前回のソースコードから編集のアイコンを追加しました。
このアイコンをクリックすると Vue.js で設定したeditメソッドが起動します。
editメソッドには作成日時とインデックスを引数に入れます。
JavaScript ( Vue.js )
editメソッド
ソースコード
edit: function(index) {
    this.editIndex = index;                         // インデックス
    this.inputText = this.list[index].task;         // タスク内容
    this.created_at = this.list[index].created_at;  // 日時
    this.$refs.editor.focus();                      // フォーカスを設定
},
解説
編集ボタン(鉛筆のアイコン)をクリックしたときに起動されるメソッドです。
選択したインデックスをもとに該当するタスク内容と日時を抽出します。
最後に入力テキストにフォーカスをアクティブにします。
算出プロパティ
ソースコード
computed: {
    changeButtonText() {
        return this.editIndex === -1 ? "追加" : "編集";
    }
},
解説
デフォルトでは editIndex には "-1" を入れています。
編集ボタンを押すと後述する editメソッド が起動して editIndex にtodo[] のインデックスを入れます。
つまり editIndex は "-1" 以外は編集モードになります。
送信メソッド
ソースコード
send: function () {
    console.log('送信機能');
    if(this.editIndex === -1) {
        // 追加
        if(!todo.last){  // 最終更新日がNULLのとき
            todo.last = { created_at: "1970-01-01 00:00:00" }
        }
        sendMessage(this.inputText, todo.last.created_at);
        this.inputText = ""; //初期化
    } else {
        // 編集
        editMessage(this.inputText, this.created_at);
    }
},
解説
送信ボタンをクリックするとsendメソッドが起動するように、Blade側でv-on:click="send"の設定をします。
editIndex の値によって『追加』か『編集』かを条件で分岐させます。
editIndex が "-1" 以外の場合は後述する editMessage関数が起動するようにします。
editMessage関数には入力された文字 ( inputText ) と 更新日時 ( created_at ) を引数にいれます。
更新日時を引数に入れた理由は API側で使うためです。
どのレコードかを識別させるためにwhere句で使用します。
クリアメソッド
ソースコード
cancel:function() {
    this.inputText = "";  // 編集覧の状態をクリア
    this.editIndex = -1; //「追加」状態に戻す
},
解説
この関数は入力状態をクリアにして、送信ボタンを「追加」の状態にするメソッドです。
Ajax通信による処理が成功し、list配列のリロード処理が終わったらこの関数を実行させます。
JavaScript ( Ajax.js )
メッセージ編集関数
ソースコード
function editMessage(message,created_at) {
    console.log('editMessage関数 起動!');
    $.ajaxSetup({
        headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') }
    });
    $.ajax({
        type: "POST",
        url: baseURL + '/edit_message_api',
        dataType: "json",
        data: { "message": message , "created_at": created_at }
    }).done(function(results) {
        console.log("メッセージ編集成功!");
        console.log('results=',results);                            // デバッグ
        changeMessage(results);
    }).fail(function(jqXHR, textStatus, errorThrown) {
        alert('メッセージを送信に失敗しました。');
        console.log("ajax通信に失敗しました");
        console.log("jqXHR          : " + jqXHR.status);     // HTTPステータスが取得
        console.log("textStatus     : " + textStatus);        // タイムアウト、パースエラー
    });
};
解説
Ajax通信でAPIにアクセスします。
「入力された文字」と「更新日時」をパラメータとして送ります。
baseURL + '/edit_message_api' にアクセスするとLaravelのコントローラが起動するようにルーティングさせます。
baseURL は変数です。
var baseURL = location.origin + "/practice/vue";
Laravel
ソースコード( Route )
Route::post('vue/edit_message_api',  'PracticeVueApiController@editMessage');   // メッセージ編集API
解説
Ajaxで vue/edit_message_api が叩かれると PracticeVueApiController の editMessage メソッドが起動。
ソースコード( Controller )
public function editMessage(Request $request) {
    $messages = DB::transaction(function() use($request)
    {
        Todo::where('created_at',$request['created_at'])->update(['task' => $request->message]);
        // 表示させるレコード
        $updateList = Todo::where('created_at', $request['created_at'])->orderBy('created_at', 'asc')->get();
        return $updateList;
    });
    return response()->json(['tasks' => $messages]);
}
解説
ビュー側で選択されたレコードを抽出して更新作業をします。
返り値を json形式に変換してAjaxの.doneに返します。
返り値は results にして changeMessage 関数を起動。
JavaScript
メッセージ変更関数
ソースコード
function changeMessage(results) {
    console.log('changeMessage起動');
    //ここでforeachなどで値を変更
    //dataの値をリロードする。
    $.each(results.tasks, function() {
        // 配列から要素を削除・追加して組み替える
        todo.list.splice(todo.editIndex, 1,this);
    });
    todo.cancel(); // 入力文字と編集用のフラグをクリア
    todo.$forceUpdate(); //DOMの再評価
}
解説
Ajax が成功したらこの関数を実行させます。
非同期で変更内容を反映させる処理をここに記述します。
jQuery.each では this は要素を指します。
var a=[1,2,3,4,5]
//jQuery
$.each(a,function(){console.log(this); //1,2,3,4,5が、Numberクラスに変換されて表示される
});
 
以上で『Vue.js + Ajax + Laravel で作成する TO DOリストの作成』のシリーズを終わらせていただきます。
なお、このシリーズは「チュートリアル中級」にて、まとめました。
復習される方はこちらをご参考ください。
基礎から学ぶ Vue.js
僕は基本的にネットで勉強しているのですが、最終的に知識を整理するために、この本を手にとって知識を整理しました。表紙のVロゴより目立っている「ねこちゃん」は本文中でもよく登場します。一部では猫本と呼ばれているそうですね。中もカラフルで図表も多く、とても読みやすかったです。当サイトは Laravel の解説サイトなので Vue.js の解説は端折っています。わかりずらいところがあるかもしれません。そういう方はこの本を読めば理解できるかと思います。

仕事で Laravel を使っています。気づいたことや新しい発見など情報を発信していきます。問い合わせはこちら。