Reputation: 13
I am building my first Angular application (a task manager), and I need to call the addItem() function at random time intervals. Do I need to use setTimeOut in this case? And where do I need to put this function call in the component TypeScript file exactly? It seems like no matter where I put it, the compiler gives an error.
Here is my tasks.component.ts file:
import { Component, OnInit } from '@angular/core';
export interface Task {
id: number;
title: string;
description: string;
priority: string;
dueDate: Date;
resolvedAt: string;
}
const defaultTaskList: Task[] = [
{
id: 1,
title: 'Get groceries',
description: 'Milk, Eggs, Bread, Salt',
priority: 'medium',
dueDate: new Date(2022, 5, 9),
resolvedAt: new Date(2022, 5, 9).toDateString(),
},
{
id: 2,
title: 'Send important emails',
description: 'Send email to tax office, include reference number: 372983.',
priority: 'high',
dueDate: new Date(2022, 5, 2),
resolvedAt: '',
},
{
id: 3,
title: 'Take Randy the dog to the vet',
description: 'Price of visit: 30 Euros. Withdraw cash.',
priority: 'medium',
dueDate: new Date(2022, 5, 13),
resolvedAt: new Date(2022, 5, 9).toDateString(),
},
{
id: 4,
title: 'Water Jane\'s plants',
description: 'Let the soil get fully soaked with water.',
priority: 'high',
dueDate: new Date(2022, 7, 11),
resolvedAt: '',
},
{
id: 5,
title: 'Do coding homework',
description: 'Details in email.',
priority: 'high',
dueDate: new Date(2021, 2, 5),
resolvedAt: '',
},
];
let tasks: Task[] = [];
let resolvedTasks: Task[] = [];
@Component({
selector: 'app-tasks',
templateUrl: './tasks.component.html',
styleUrls: ['./tasks.component.scss'],
})
export class TasksComponent implements OnInit {
displayedColumns: string[] = ['id', 'title', 'description', 'priority', 'dueDate', 'resolvedAt'];
dataSource = tasks;
resolvedDataSource = resolvedTasks;
addItem(): void {
let i = Math.floor(Math.random() * defaultTaskList.length);
let currentTask: Task = defaultTaskList[i];
let newData = [ ...this.dataSource ];
let newResolvedData = [... this.resolvedDataSource];
if (currentTask.resolvedAt) {
newResolvedData.push(currentTask)
} else {
newData.push(currentTask);
}
newData = newData.sort((a, b) => {
return a.dueDate.getTime() - b.dueDate.getTime();
});
newResolvedData = newResolvedData.sort((a, b) => {
return a.dueDate.getTime() - b.dueDate.getTime();
});
newData.map((obj) => {
return { ...obj, dueDate: obj.dueDate.toDateString() };
});
newResolvedData.map((obj) => {
return { ...obj, dueDate: obj.dueDate.toDateString() };
});
this.dataSource = newData;
this.resolvedDataSource = newResolvedData;
}
constructor() { }
ngOnInit(): void {
}
}
and my tasks.component.html file:
<table mat-table [dataSource]="dataSource">
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef>ID</th>
<td mat-cell *matCellDef="let task">{{task.id}}</td>
</ng-container>
<ng-container matColumnDef="title">
<th mat-header-cell *matHeaderCellDef>Title</th>
<td mat-cell *matCellDef="let task">{{task.title}}</td>
</ng-container>
<ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef>Description</th>
<td mat-cell *matCellDef="let task">{{task.description}}</td>
</ng-container>
<ng-container matColumnDef="priority">
<th mat-header-cell *matHeaderCellDef>Priority</th>
<td mat-cell *matCellDef="let task">{{task.priority}}</td>
</ng-container>
<ng-container matColumnDef="dueDate">
<th mat-header-cell *matHeaderCellDef>Due date</th>
<td mat-cell *matCellDef="let task">{{task.dueDate | date:'longDate'}}</td>
</ng-container>
<ng-container matColumnDef="resolvedAt">
<th mat-header-cell *matHeaderCellDef>Resolved at</th>
<td mat-cell *matCellDef="let task">{{task.resolvedAt | date:'longDate'}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<h2>Resolved</h2>
<table mat-table [dataSource]="resolvedDataSource">
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef>ID</th>
<td mat-cell *matCellDef="let task">{{task.id}}</td>
</ng-container>
<ng-container matColumnDef="title">
<th mat-header-cell *matHeaderCellDef>Title</th>
<td mat-cell *matCellDef="let task">{{task.title}}</td>
</ng-container>
<ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef>Description</th>
<td mat-cell *matCellDef="let task">{{task.description}}</td>
</ng-container>
<ng-container matColumnDef="priority">
<th mat-header-cell *matHeaderCellDef>Priority</th>
<td mat-cell *matCellDef="let task">{{task.priority}}</td>
</ng-container>
<ng-container matColumnDef="dueDate">
<th mat-header-cell *matHeaderCellDef>Due date</th>
<td mat-cell *matCellDef="let task">{{task.dueDate | date:'longDate'}}</td>
</ng-container>
<ng-container matColumnDef="resolvedAt">
<th mat-header-cell *matHeaderCellDef>Resolved at</th>
<td mat-cell *matCellDef="let task">{{task.resolvedAt | date:'longDate'}}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<button mat-button (click)="addItem()">Add new item</button>
Also, I take any suggestions regarding Angular and TS best practices, or how to make the code more simple and readable.
Thanks!
Upvotes: 0
Views: 302
Reputation: 36309
You can use an interval to call your function at a minimum speed and filter out the value to randomize the rate that your function is called.
ngOnInit() {
// 250 is the minimum speed at which the function will be called
this.sub = interval(250)
.pipe(
// Generate a random number
map(() => Math.round(Math.random() * 10)),
// Use the random number to filter, it should be between 0 and 3
// A bigger range will call the function more often
// A smaller range will call the function less often
filter((i) => i > 0 && i < 3),
// If the number gets this far call your function
tap(() => this.myFunc())
)
// Don't forget to unsubscribe when your done,
// otherwise the function will keep getting called.
.subscribe();
}
You can see a working example here
Upvotes: 1