Part 5: The Screen & Form Elements
Overview
Completed code: live example / download example
Step 1: ScreenComponent
The ScreenComponent serves as the primary component for our form interactions. While ProcessMaker permits several forms within a single Screen, each task should associate with one Screen that can encompass multiple forms. Any task should have a single Screen, but can have multiple forms. They will be contained within an array in the response payload when making the API request.
When we get the form part, we will use the FormComponent as well as others to ultimately render the form.
The ScreenComponent is passed the required data that will be passed down through to the individual elements on the form.
Template
app-screen.component.html
<!-- Use app-form-element to render form elements -->
<app-form
*ngFor="let screen of screens?.config"
[form]="screen"
[request]="request"
[css]="screens.custom_css"
[computed]="screens.computed">
</app-form>Typescript
app-screen.component.ts
import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { TasksService, ProcessRequestsService } from 'api';
import { DbService } from 'src/app/services/db.service';
@Component({
selector: 'app-screen',
templateUrl: './app-screen.component.html',
})
export class ScreenComponent implements OnInit {
// Define the request object, type can be further specified
request: any;
// Define properties with appropriate types
exists: any; // Define the type as per your requirements
processRequestId: number | null = null; // Define the type as number or null
taskId: number | null = null; // Define the type as number or null
@Output() screens: any; // Define the type as per your requirements
data: any; // Define the type as per your requirements
response: any; // Define the type as per your requirements
screenConfig: any;
@Output() screenEvent: EventEmitter<any> = new EventEmitter(); // Define the type as per your requirements
constructor(
private route: ActivatedRoute,
private router: Router,
public requestApi: ProcessRequestsService,
public tasksApi: TasksService,
private db: DbService
) {}
ngOnInit(): void {
console.log(this);
// Parse the values as numbers, and handle the possibility of null values
// Convert processRequestId and taskId from string to number, handle null values
this.processRequestId =
Number(this.route.snapshot.paramMap.get('processRequestId')) || null;
this.taskId = Number(this.route.snapshot.paramMap.get('taskId')) || null;
// Check if taskId is not null before proceeding
if (this.taskId !== null) {
// Set the credentials for the tasks API
this.tasksApi.configuration.credentials['pm_api_bearer'] =
this.db.load('access_token') || '';
// Fetch the task by ID and include specific related data
this.tasksApi
.getTasksById(
this.taskId,
'processRequest,user,data,screen,definition,screenRef'
)
.subscribe(
(response) => {
// Assign the response to the request object
this.screens = response.screen;
this.request = response.data;
//console.log(this);
},
(error) => {
// Log any errors
}
);
}
}
handleScreenEvent(event: any) {
// Handle any screen-related event here
this.screenEvent.emit(event);
}
}
Step 2: FormComponent
Given that a Screen can associate with multiple forms, our design ensures minimal code adjustments to accommodate this.
The FormComponent passes through to the form element the request data and definitions for the different elements.
Template
Typescript
Step 3: FormElementComponent
Our application design emphasizes easy extensibility and customization. As of the time of this writing, the form elements are supported and shipped with the app. However, as you will see, it is relatively easy to add more elements.
Form Elements
The FormElementComponent is utilized to render varied components, managing logic via ngSwitch.
The main FormElementComponent class should be placed at src/app/components/form-element/app-form-element.component.ts and src/app/components/form-element/app-form-element.component.html, respectively.
The various form elements are contained with src/app/components/form-element/elements.
Example: src/app/components/form-element/elements/app-element-input.component.ts
Input
Template
Typescript
Image
Template
Typescript
Multi Column
Template
Typescript
Upload File
Template
Typescript
Buttons
Template
Typescript
HTML Viewer
Template
Typescript
Default
Template
Typescript
Step 4: Updates
Now that our app is almost complete, we just need to update the router so it knows where to go when we click on the "View Task" button.
The Router
AppModule
We need to add all the new components to our AppModule.
Typescript
Review
After your code finishes compiling, click on the "Next Task" button in the inbox (assuming you have open cases) and you should see your form, just as I have posted a screenshot below.

We recommend playing around with simple forms first, and then adding complexity as you get more comfortable.
If you liked this or found it helpful, please let us know by leaving a rating and sharing on social!
If not, please let us know!
PRs are always welcomed!
Last updated