10.9: Deleting Messages

Now we'll implement deleting messages. As explained earlier - we'll only actually delete the message if both users delete it. Otherwise, we'll mark it as deleted for that user and not display it for them.

Deleting Messages in the API

We'll start off in the .API and we'll implement a DeleteMessage() method in MessageController.cs. Because we aren't necessarily deleting a message - we'll make it a POST instead of a DELETE.

[HttpPost("{id}")]
public async Task<IActionResult> DeleteMessage(int id, int userId)
{
    if (userId != int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value))
        return Unauthorized();

    var message = await _messageService.GetMessage(id);

    if (message.SenderId == userId)
        message.SenderDeleted = true;

    if (message.RecipientId == userId)
        message.RecipientDeleted = true;

    if (message.SenderDeleted && message.RecipientDeleted)
        _userService.Delete(message);

    if (await _messageService.SaveAll())
        return NoContent();

    throw new Exception("Error deleting the message");
}

We'll check whether the sender or receiver are requesting the delete and mark the corresponding deleted property to true.

If both are true - we use our generic Delete() method to delete the Message from the database.

We already added checks in our MessageService in the GetMessagesForUser() and GetMessageThread() methods to see if a message is marked as deleted before returning it to a user.

Deleting Messages in Angular

As usual, we'll start in our UserService and add a method. This time it will be deleteMessage().

deleteMessage(id: number, userId: number) {
    return this._http.post(this.baseUrl + 'users/' + userId + '/messages/' + id, {});
}

Next, in messages.component.ts we'll add a method - also called deleteMessage().

We'll also need to import underscore to make use of their splice() function:

import * as _ from 'underscore';
deleteMessage(id: number) {
    this._alertify.confirm('Are you sure you want to delete the message?', () => {
      this._userService.deleteMessage(id, this._authService.decodedToken.nameid).subscribe(() => {
        this.messages.splice(_.findIndex(this.messages, {id: id}), 1);
        this._alertify.success('Message has been deleted');
      }, error => {
        this._alertify.error('Failed to delete the message');
      });
    });
}

We'll use Alertify to prompt the user to confirm they want to delete the message.

If they do, we'll send the request to our "delete" endpoint and remove it from the messages array in the component.

Finally, in messages.component.html, we'll add a click listener to the Delete button.

<td><button class="btn btn-danger" (click)="deleteMessage(message.id)"><i class="fa fa-trash-o mr-1"></i>Delete</button></td>

Right now, it works. But, because the parent element wants to redirect us to the MemberDetail template with the Messages tab opened - this click event propagates to the parent redirect - which, we don't want in this case.

This can be prevented by added a second click event to the element:

<td><button class="btn btn-danger" (click)="$event.stopPropagation()" (click)="deleteMessage(message.id)"><i class="fa fa-trash-o mr-1"></i>Delete</button></td>

Last updated