Building a to-do list app (part 4)

May 13, 2021

Reusing the TaskEditor component

The edit section for tasks and the section for adding a new tasks has lots of similarities. I decided to use the TaskEditor component for both. The main difference, in terms of passing data, is that task adders don’t get existing task name or due time.

Data that may be passed To task editor To task adder
Min of new due time range Yes Yes
Max of new due time range Yes Yes
Existing task name Yes No
Existing due time Yes No

A ref attribute is needed in both to focus the input field when the adder/editor is revealed:

showEditSection() {
    this.isEditing = true;
    this.$nextTick(() => {
        this.$refs.taskEditorComp.$refs.newNameInput.focus();
    });
},
showAdderSection() {
    this.isAddingTask = true;
    this.$nextTick(() => {
        this.$refs.taskAdderComp.$refs.newNameInput.focus();
    });
},

WebSockets

We have three main parties here: the Laravel server, the WebSockets server, and the front-end.

So, this is how things work.

The Laravel server is always running. In localhost, you run it manually with the php artisan serve command. And a Laravel app is usually automatically served on (and by) a hosting. What more is needed is a WebSockets server which needs to be constantly running as well. You run that with the php artisan websockets:serve command in the local environment. (It’s different for production.)

Now, if the Laravel back-end wants to let the front-end know about something, it can inform the WebSockets server and that can send data to the front-end.

But the front-end must have some arrangement for receiving the data. That’s where Echo comes in. You set up a listener with Echo that, well, listens to any message/data from the WebSockets server.

And that’s the gist of it, really.

Here’s a simplified representation:

                                                            Front-end
Laravel server             WebSockets server                 Echo  |
      |                            |                          |    |
      |                            |     Starts connection    |    |
      |                            |<-------------------------|    |
      |                            |     & keeps listening    |    |
      |                            |                          |    |
      |<--- Makes some change -------------------------------------|
      |                            |                          |    |
      |--- Tells about change ---->|                          |    |
      |                            |                          |    |
      |                            |    Sends data without    |    |
      |                            |------------------------->|    |
      |                            |   action from front-end  |    |
      |                            |                          |    |

Of course, there are technical details in every step.

For example, the Laravel server lets the WebSockets server know something happened by broadcasting “events”. In this case, it’s a TaskUpdated event. Whenever some data of a task is updated, this event is fired from relevant functions in TaskController.php.

So, we create an event class using this Artisan command:

php artisan make:event TaskUpdated

Then add a line to broadcast an event at the necessary places inside TaskController.php:

public function update(Request $request, Task $task)
{
    // Code for updating task

    broadcast( new TaskUpdated() );
}

Inside the TaskUpdated.php file, we need to implement the ShouldBroadcast interface, get tasks from the database and save them in a variable, and broadcast them to the front-end:

public $tasks;

public function __construct() {
    $this->tasks = Task::all();
}

public function broadcastWith() {
    return [ 'allTasks' => $this->tasks ];
}

Echo on the front-end needs to listen to this. But since there could be many such broadcasts about many different events, we need something to differentiate theme. So, TaskUpdated.php will broadcast on a “channel” with a specific name which Echo will listen to:

public function broadcastOn() {
    return new Channel('all-tasks');
}
window.Echo.channel('all-tasks')
    .listen('TaskUpdated', (data) => {
        this.tasks = data.allTasks;
    });

These were only some of the details though. Mantle shows tasks in a nicely ordered fashion, with “done” tasks shown after the “not done” ones and so on. Plus, an event is also broadcast when a task is removed or a new one is created.


Check out Mantle on GitHub here

projectMantleVueLaravelWebSocketsto-do list

Building a to-do list app (part 5)

Building a to-do list app (part 3)