Displaying state changes in our templates

Now that we can pick the tasks to be done from the table, it would be great to have some kind of visual hint of how many units we are meant to ship. The logic is as follows:

  • The user reviews the tasks on the table and picks the ones to be done by clicking on each one
  • Every time a row is clicked, the underlying Task object state changes and its Boolean queued property is toggled
  • The state change is reflected immediately on the surface by displaying a queued label on the related task item
  • The user gets prompt information of the amount of units they need to ship and a time estimation to deliver them all
  • We see how a row of icons are displayed above the table, displaying the sum of all units from all the tasks set to be done

This functionality will have to react to the state changes of the set of Task objects we're dealing with. The good news is that thanks to Angular's very own change detection system, making components fully aware of state changes is extremely easy.

Thus, our very first task will be to tweak our TasksComponent class to include some way to compute and display how many tasks are queued up. We will use that information to render or not a block of markup in our component where we will inform how many tasks we have lined up and how much aggregated time it will take to accomplish them all.

The new queuedTasks field of our class will provide such information, and we will want to insert a new method named updateQueuedTasks() in our class that will update its numeric value upon instantiating the component or enqueueing tasks. On top of that, we will create a key/value mapping that we can use later on to render a more expressive title header depending on the amount of queued tasks thanks to the I18nPlural pipe:

class TasksComponent {
today: Date;
tasks: Task[];
queuedTasks: number;
queuedHeaderMapping: any = {
'=0': 'No tasks',
'=1': 'One task',
'other' : '# tasks'
};

constructor() {
const TasksService: TasksService = new TasksService();
this.tasks = tasksService.tasksStore;
this.today = new Date();
this.updateQueuedTasks();
}

toggleTask(task: Task) {
task.queued = !task.queued;
this.updateQueuedTasks();
}

private updateQueuedTasks() {
this.queuedTasks = this.tasks
.filter( task:Task => task.queued )
.reduce((hoursLeft: number, queuedTask: Task) => {
return hoursLeft + queuedTask.hoursLeft;
}, 0)
}
}

The updateQueuedTasks() method makes use of JavaScript's native Array.filter() and Array.reduce() methods to build a list of queued tasks out of the original task's collection property. The reduce method applied over the resulting array gives us the total number of units to ship. With a stateful computation of the number of queued units to ship now available, it's time to update our template accordingly. Go to  tasks.html   and inject the following chunk of HTML right before the <h4>Tasks backlog</h4> element. The code is as follows:

<div>
<h3>
{{queuedTasks | i18nPlural:queueHeaderMapping}}
for today
<span class="small" *ngIf="queuedTasks > 0">
(Estimated time: {{ queuedTasks > 0 }})
</span>
</h3>
</div>
<h4>Tasks backlog</h4>
<!-- rest of the template remains the same -->

The preceding block renders an informative header title at all times, even when no tasks have been queued up. We also bind that value in the template and use it to estimate through an expression binding the amount of minutes required to go through each and every session required.

We are hardcoding the duration of each task in the template. Ideally, such constant values should be bound from an application variable or a centralized setting. Don't worry, we will see how we can improve this implementation in the next chapters.

Save your changes and reload the page, and then try to toggle some task items on the table to see how the information changes in real time. Exciting, isn't it?

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset