Work Laravel 5.3 + Vue.JS 1.0 - Add Update and Delete Functionality

Laravel 5.3 + Vue.JS 1.0 - Add Update and Delete Functionality

23rd Sep, 2016 | Work

PS: Continuation of our Laravel + VueJS series.

So far we can create and read mailing lists.
Today, we will add the Update and Delete functionalities and wire up our mailing list application as a complete CRUD app. If you just want to see the code, here it is on the Github.

Update Operation

In our VueJS view, we will add a button for each mailing list which when clicked, will trigger a method that performs a GET request on the server to fetch the server copy of the mailing list. Upon success, this method will then set a flag that notifies our app that we are editing a mailing list, toggling the 'add mailing list' and 'edit mailing list' forms and pre-populating the latter with the result of the GET call. The user can then edit the mailing list and submit the form which would call a method that performs a PUT request to the server in order to update our mailing list. The server would respond with the new mailing list and the ViewJS method will then notify our app that we are no longer editing a mailing lis and toggle back the two forms.

Here are the two forms:

<form v-on:submit='addMList' v-if='! editingMList'>
    <div class="form-group">
        <input class="form-control" placeholder="New Mailing List" v-model="newMList.name">
    </div>
    <!--<button class="btn btn-default">Create</button>-->
</form>
<form v-on:submit='updateMList' v-if='editingMList'>
    <div class="form-group">
        <input class="form-control" placeholder="Mailing List" v-model="editMList.name">
    </div>
    <!--<button class="btn btn-default">Create</button>-->
</form>

You will notice that we are showing one when editingMList is true and the other when it's false. So in our data function inside the script section of our component, we will have initialized both editingMList (false) and editMList (empty object - this would contain the mailing list being edited). See code.

Next up is to add the 'edit' buttons inside the repeater:

<tr v-for="mList in mLists | orderBy orderAttr orderToggle">
    <td>{{ mList.name }}</td>
    <td>{{ mList.created_at | localTime }}</td>
    <td>{{ mList.updated_at | localTime }}</td>
    <td><i class="fa fa-pencil-square-o btn btn-default btn-xs" @click="fetchMList(mList)"></i></td>
    <td><i class="fa fa-times btn btn-danger btn-xs" @click="deleteMList(mList)"></i></td>
</tr>

In the code above, we have actually added both the 'edit' and 'delete' buttons.

Now we need to define the method that would handle the onclick event on the 'edit' button:

fetchMList: function(mList) {
    if ( mList && mList.id ) {
        var progress = this.$Progress;
        progress.start();

        this.$http.get(this.resourceUrl + '/' + mList.id).then(function (response) {
            if (response.data && response.status == 200) {
                progress.finish();
                this.editingMList = true;
                this.editMList = response.data;
            }
        }, function (error) {
            swal('An Error Occurred', 'Please refresh the page and try again.', 'error');
            progress.fail();
        });
    }
    else
        swal('An Error Occurred', 'Please refresh the page and try again.', 'error');
}

The method will attempt to fetch the mailing list from the server and then update the value of editMList that we would have set in our data function. It will also toggle the value of editingMList so that the correct form can be shown on the page. Here is the Laravel code that handles the server side of things:

/**
 * Display the specified resource.
 *
 * @param  int  $id
 * @return \Illuminate\Http\Response
 */
public function show($id)
{
    if ( $mList = MailingList::find($id) )
        return $mList;
    else
        return response()->json(['error' => 'Mailing list does not exist']);
}

When the user is done editing the mailing list, then would then submit the form to the updateMList method:

updateMList: function(e) {
    e.preventDefault();
    var that = this;
    var progress = that.$Progress;
    var editMListName = that.editMList.name.trim();

    if ( editMListName ) {
        progress.start();
        that.editMList.name = editMListName;

        that.$http.put(that.resourceUrl + '/' + that.editMList.id, that.editMList).then(function(response) {
            swal({
                title: "Success",
                text: 'Mailing List updated',
                type: 'success',
                animation: 'slide-from-bottom',
                timer: 3000
            });

            that.editMList = {};
            that.editingMList = false;
            progress.finish();
            that.fetchMLists();
        }, function(error) {
            if ( error.status && error.status == 422 && error.data.name ) {
                swal('An Error Occurred', error.data.name, 'error');
            }
            else {
                swal('An Error Occurred', 'Please refresh the page and try again.', 'error');
            }
            progress.fail();
        });
    }
}

And on the server, here is the method that would handle the updating:

/**
 * Update the specified resource in storage.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  int  $id
 * @return \Illuminate\Http\Response
 */
public function update(Request $request, $id)
{
    if ( $mList = MailingList::find($id) ) {

        if ( $mList->name != trim($request->name) ) {
            $this->validate($request, $this->rules);

            $mList->name = trim($request->name);
            $mList->save();
        }

        return $mList;
    }
    else
        return response()->json(['error' => 'Mailing list does not exist']);
}

And that's it for the Update operation.

Delete Operation

This one is simple. All we have to do is add a 'delete' button for each mailing list (already done in the code above) and then listen to click event on the button, issue a command to the server and then have a good day. In the buttons code above, you will see that we call the deleteMList() method and pass it the mailing list.

Here's the method:

deleteMList: function(mList) {
    var that = this;
    var progress = this.$Progress;

    swal({
            title: "Delete mailing list: " + mList.name + "?",
            text: "You will not be able to recover this mailing list. Subscribers won't be deleted.",
            type: "warning",
            showCancelButton: true,
            confirmButtonColor: "#DD6B55",
            confirmButtonText: "Delete!",
            closeOnConfirm: false
        }, function() {
            progress.start();

            that.$http.delete(that.resourceUrl + '/' + mList.id).then(function(response) {
                if ( response.data && response.data.success ) {
                    swal({
                        title: "Success",
                        text: response.data.success,
                        type: 'success',
                        animation: 'slide-from-bottom',
                        timer: 3000
                    });

                    progress.finish();
                    that.fetchMLists();
                }
            }, function(error) {
                if ( error.data && error.data.error )
                    swal('An Error Occurred', error.data.error, 'error');
                else
                    swal('An Error Occurred', 'Please refresh the page and try again.', 'error');
                progress.fail();
            });
        });
}

We actually prompt the user for a confirmation before we issue the DELETE request on the server. The server code looks like this:

/**
 * Remove the specified resource from storage.
 *
 * @param  int  $id
 * @return \Illuminate\Http\Response
 */
public function destroy($id)
{
   if ( $mList = MailingList::find($id) ) {
       $mList->delete();
       return response()->json(['success' => 'Mailing list successfully deleted']);
   }
   else
       return response()->json(['error' => 'Mailing list does not exist']);
}

The server simply deletes the mailing list if found and then responds appropriately.

And with that, our CRUD application is complete:

All code at this point in the process is this way.

 

 

Comments