Part 4: The Inbox


With the core services and components in place, we'll now interface with the ProcessMaker API.

Completed code: live example / download example

Step 1: Environment Details

Ensure you have the subsequent details ready for this section:

  • Client ID

  • Client Secret

  • FQDN for your ProcessMaker installation

  • OAuth Token URL

  • OAuth Redirect URI

  • OAuth Authorization URL

You can see what a sample environment.ts file looks like below. This is where you will add the above information.

export const environment = {
	production: false,
	apiDomain: 'localhost',
	apiPath: '/api/1.0',
	apiProtocol: 'http://',
	clientId: '19',
	clientSecret: 'Psn9cxcGFKO1GO4ZZ9TgOhQtAjt0Wmzjc58vw8Lq',
	oauthUrl: 'http://localhost/oauth/token',
	redirectUri: 'http://localhost:4200/#/oauth/callback',
	oauthAuthorizeUrl: 'http://localhost/oauth/authorize',
	customCss: false,
	calcProps: true,

Step 2: TasksComponent

The TasksComponent relies on the ScreenComponent, which we'll address in the subsequent section. We'll omit it for now and reintroduce it when we're set to render the form.


<div class="container-fluid">
	<div class="table-container mt-4">
		<div class="mb-2">
			<h2>Your pending tasks</h2>
			<h5 class="text-secondary">View your assigned tasks.</h5>
		<table id="mytable" class="table align-middle mb-0 bg-white">
			<thead class="bg-light">
				<tr class="header-row">
					<th>ID #</th>
					<th>Task Name</th>
				<tr *ngIf="!userTasks.length">
					<td colspan="6">
				<tr *ngFor="let task of userTasks">
						<p class="fw-bold fw-normal mb-1">{{ task.process_request_id }}</p>
						<p class="fw-bold fw-normal mb-1">{{ task.element_name }}</p>

						<div [ngSwitch]="task.advanceStatus">
								class="badge badge-danger rounded-pill d-inline"
								style="text-transform: capitalize"
								>{{ task.advanceStatus }}</span
								class="badge badge-primary rounded-pill d-inline"
								style="text-transform: capitalize"
								>{{ task.advanceStatus }}</span
								class="badge badge-success rounded-pill d-inline"
								style="text-transform: capitalize"
								>{{ task.advanceStatus }}</span

					<td>{{ task.user.firstname }} {{ task.user.lastname }}</td>
					<td>{{ }}</td>
							<span>{{ task.due_at }}</span>
							class="btn btn-link btn-sm btn-rounded text-primary">
							<i class="me-1 bi-window-sidebar text-primary"></i>
							View Task


// Import necessary Angular core modules
import { Component, OnInit } from '@angular/core';
// Import Angular routing modules
import { ActivatedRoute, Router } from '@angular/router';
// Import services related to ProcessRequests and Tasks
import { ProcessRequestsService, TasksService } from 'api';
// Import local database service
import { DbService } from 'src/app/services/db.service';

// Define the Task interface to represent the structure of a task
interface Task {
	process_request_id: string; // ID of the associated process request
	element_name: string; // Name of the element
	advanceStatus: string; // Status of the task advancement
	user: { firstname: string; lastname: string }; // User information
	process_request: { name: string }; // Process request information
	due_at: string; // Due date for the task
	id: string; // Unique ID for the task

// Component metadata
	selector: 'app-tasks', // Selector used in templates
	templateUrl: './app-tasks.component.html', // Path to the HTML template
// TasksComponent class definition
export class TasksComponent implements OnInit {
	// Pagination properties
	pagination = {
		currentPage: 1, // Current page number
		itemsPerPage: 10, // Number of items per page
		lastPage: null, // Last page number
		totalItems: null, // Total number of items

	// Selected request and task properties
	selectedRequest: Request | null = null;
	selectedTask: Task | null = null;
	userTasks: Task[] = []; // Array to hold user tasks
	color = 'green'; // Color property (usage not shown in provided code)

	// Constructor with dependency injection
		private requestApi: ProcessRequestsService, // Process request service
		private tasksApi: TasksService, // Task service
		private route: ActivatedRoute, // Activated route information
		private router: Router, // Router service for navigation
		private db: DbService // Database service
	) {}

	// ngOnInit lifecycle hook
	ngOnInit() {
		// Load access token from the database
		const accessToken = this.db.load('access_token') as string | undefined;
		// If access token exists, set it in the task API configuration
		if (accessToken) {
			this.tasksApi.configuration.credentials['pm_api_bearer'] = accessToken;

		// Call getTasks method from tasksApi with parameters null and 'ACTIVE'
		this.tasksApi.getTasks(undefined, 'ACTIVE').subscribe(
			(response: any) => {
				// Handle successful response
				this.userTasks =; // Assign user tasks from response data
				// Create a new ScreenComponent instance
			(error) => {
				// Handle error response
				console.log(error); // Log the error to the console

	// Method to open a form with given processRequestId and taskId
	openScreen(processRequestId: string, taskId: string) {
		// Navigate to the 'form' route with parameters
				processRequestId: processRequestId,
				taskId: taskId,

	// Placeholder method for getting a user task by ID
	getUserTask(id: string) {}

	// Placeholder method for getting user tasks by ID
	getUserTasks(id: string) {}

Step 3: Update the Router

Integrate the new components and their respective paths into the router. The following code demonstrates how to import these components and establish a route for the inbox view.

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { LoginComponent } from '../components/login/login.component';
import { TasksComponent } from '../components/tasks/app-tasks.component';
import { AuthGuard } from '../guards/auth.guard';

const routes: Routes = [
		path: 'login',
		component: LoginComponent,
		runGuardsAndResolvers: 'always',
		title: 'Login',
		path: 'oauth/callback',
		component: LoginComponent,
		runGuardsAndResolvers: 'always',
		path: 'tasks',
		component: TasksComponent,
		canActivate: [AuthGuard],
		runGuardsAndResolvers: 'always',
		title: 'Inbox',
		path: '',
		redirectTo: 'tasks',
		pathMatch: 'full',
		runGuardsAndResolvers: 'always',
		path: '**',
		redirectTo: 'tasks',
		runGuardsAndResolvers: 'always',

	imports: [RouterModule.forRoot(routes, { useHash: true })],
	exports: [RouterModule],
export class AppRoutingModule {}

Step 4: Update AppModule

Now we just need to incorporate the TasksComponent into the AppModule declaration.

import { NgModule } from '@angular/core';
import '@angular/compiler';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { AppRoutingModule } from './routing/app-routing.module';
import { RootComponent } from './components/root/app-root.component';
import { LoginComponent } from './components/login/login.component';
import { NavigationComponent } from './components/nav/navigation.component';
import { AppBreadcrumbsComponent } from './components/breadcrumbs/app-breadcrumbs.component';
import { TasksComponent } from './components/tasks/app-tasks.component';

	declarations: [
	imports: [
	providers: [],
	bootstrap: [RootComponent],
export class AppModule {}


If you are following along with the tutorial, you should now be able to see your tasks, in your new Angular Inbox!

Next Steps

pagePart 5: The Screen & Form Elements

Last updated