> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flowx.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Angular SDK

> FlowxProcessRenderer is a library designed to render the UI of processes created via the Flowx Process Designer.

<Warning>
  **Breaking changes**: Starting with version 4.0 the ui-sdk will no longer expect the authToken to be present in the `LOCAL_STORAGE`. Instead, the authToken will be passed as an input to the flx-process-renderer component. This is mandatory for the SSE to work properly.
</Warning>

## Prerequisites

* Node.js min version 20 - [**Download Node.js**](https://nodejs.org/en/blog/release/v20.9.0)
* Angular CLI version 19.2. Install Angular CLI globally using the following command:

```npm theme={"system"}
npm install -g @angular/cli@19.2
```

This will allow you to run ng related commands from the terminal.

## Angular project requirements

Your app MUST be created using the NG app from the @angular/cli\~19.2 package. It also MUST use SCSS for styling.

```npm theme={"system"}
npm install -g @angular/cli@19.2
ng new my-flowx-app
```

<Check>
  To install the npm libraries provided by FLOWX you will need to obtain access to the private FlowX Nexus registry. Please consult with your project DevOps.
</Check>

<Info>
  The library uses Angular version **@angular\~19.2**, **npm v10.1.0** and **node v20.9.0**.
</Info>

<Check>
  If you are using an older version of Angular (for example, v16), please consult the following link for update instructions:

  [**Update Angular from v16.0 to v19.2**](https://angular.dev/update-guide?v=16.0-19.2\&l=1)
</Check>

## Installing the library

Use the following command to install the **renderer** library and its required dependencies:

```bash theme={"system"}
npm install \
  @flowx/core-sdk@<version>\
  @flowx/core-theme@<version> \
  @flowx/angular-sdk@<version> \
  @flowx/angular-theme@<version> \
  @flowx/angular-ui-toolkit@<version> \
  @angular/cdk@19.2 \
  @types/event-source-polyfill
```

<Warning>
  Replace `<version>` with the correct version corresponding to your platform version.

  To find the right version, navigate to: **Release Notes → Choose your platform version → Deployment guidelines → Component versions**.
</Warning>

A few configurations are needed in the projects `angular.json`:

* To successfully link the pdf viewer, add the following declaration in the assets property:

```json theme={"system"}
{
  "glob": "**/*",
  "input": "node_modules/ng2-pdfjs-viewer/pdfjs",
  "output": "/assets/pdfjs"
}
```

## Initial setup

Once installed, `FlxProcessModule` will be imported in the `AppModule` as `FlxProcessModule.withConfig({})`.

You **MUST** also import the dependencies of `FlxProcessModule`: `HttpClientModule` from `@angular/common/http`

### Theming

Component theming is done through the `@flowx/angular-theme` library. The theme id is a required input for the renderer SDK component and is used to fetch the theme configuration. The id can be obtained from the admin panel in the themes section.

<Frame>
  ![](https://s3.eu-west-1.amazonaws.com/docx.flowx.ai/2024-04-08%2013.45.10.gif)
</Frame>

### Authorization

<Info>
  Every request from the **FlowX** renderer SDK will be made using the **HttpClientModule** of the client app, which means those requests will go through every interceptor you define here. This is most important to know when building the auth method as it will be the job of the client app to intercept and decorate the requests with the necessary auth info (eg. `Authorziation: Bearer ...`).
</Info>

<Info>
  It's the responsibility of the client app to implement the authorization flow (using the **OpenID Connect** standard). The renderer SDK will expect the authToken to be passed to the `flx-process-renderer` as an input.
</Info>

```typescript theme={"system"}
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { FlxProcessModule } from '@flowx/angular-sdk';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    // will be used by the renderer SDK to make requests
    HttpClientModule,
    // needed by the renderer SDK
    FlxProcessModule.withConfig({
      components: {},
      services: {},
    }),
  ],
  // this interceptor with decorate the requests with the Authorization header
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

```

The `withConfig()` call is required in the application module where the process will be rendered. The `withConfig()` method accepts a config argument where you can pass extra config info, register a **custom component**, **service**, or **custom validators**.

**Custom components** will be referenced by name when creating the template config for a user task.

**Custom validators** will be referenced by name (`currentOrLastYear`) in the template config panel in the validators section of each generated form field.

```typescript theme={"system"}
// example with custom component, custom services and custom validator
FlxProcessModule.withConfig({
  components: {
    YourCustomComponentIdentifier: CustomComponent,
  },
  services: {
    NomenclatorService,
    LocalDataStoreService,
  },
  validators: { currentOrLastYear },
})

  // example of a custom validator that restricts data selection to
  // the current or the previous year

  currentOrLastYear: function currentOrLastYear(AC: AbstractControl): { [key: string]: any } {
    if (!AC) {
      return null;
    }

    const yearDate = moment(AC.value, YEAR_FORMAT, true);
    const currentDateYear = moment(new Date()).startOf('year');
    const lastYear = moment(new Date()).subtract(1, 'year').startOf('year');

    if (!yearDate.isSame(currentDateYear) && !yearDate.isSame(lastYear)) {
      return { currentOrLastYear: true };
    }

    return null;
  }
```

<Warning>
  The error that the validator returns **MUST** match the validator name.
</Warning>

The entry point of the library is the `<flx-process-renderer></flx-process-renderer>` component. A list of accepted inputs is found below:

```html theme={"system"}
<flx-process-renderer
  [apiUrl]="baseApiUrl"
  [processApiPath]="processApiPath"
  [authToken]="authToken"
  [themeId]="themeId"
  [processName]="processName"
  [processStartData]="processStartData"
  [workspaceId]="workspaceId"
  [debugLogs]="debugLogs"
  [keepState]="keepState"
  [language]="language"
  [legacyHttpVersion]="legacyHttpVersion"
  [projectInfo]="projectInfo"
  [locale]="locale",
  [cache]="cache"
/>
```

#### Parameters

| Name              | Description                                                                                                                                                                          | Type    | Mandatory | Default value | Example                                                                 |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- | --------- | ------------- | ----------------------------------------------------------------------- |
| apiUrl            | Your base url                                                                                                                                                                        | string  | true      | -             | [https://yourDomain.dev](https://yourdomain.dev)                        |
| processApiPath    | Process subpath                                                                                                                                                                      | string  | true      | -             | onboarding                                                              |
| authToken         | Authorization token                                                                                                                                                                  | string  | true      | -             | 'eyJhbGciOiJSUzI1NiIsIn....'                                            |
| themeId           | Theme id used to style the process. Can be obtained from the themes section in the admin                                                                                             | string  | true      | -             | '123-456-789'                                                           |
| processName       | Identifies a process                                                                                                                                                                 | string  | true      | -             | client\_identification                                                  |
| workspaceId       | Workspace id                                                                                                                                                                         | string  | true      | -             | '8f52744-8403-4e8d....'                                                 |
| processStartData  | Data required to start the process                                                                                                                                                   | json    | true      | -             | `{ "firstName": "John", "lastName": "Smith"}`                           |
| debugLogs         | When set to true this will print WS messages in the console                                                                                                                          | boolean | false     | false         | -                                                                       |
| language          | Language used to localize the application.                                                                                                                                           | string  | false     | en            | -                                                                       |
| keepState         | <p>By default all process data is reset when the process renderer component gets destroyed. Setting this to true will keep process data even if the viewport gets destroyed</p><p /> | boolean | false     | false         | -                                                                       |
| isDraft           | When true allows starting a process in draft state. \*Note that isDraft = true requires that processName be the **id** (number) of the process and NOT the name.                     | boolean | false     | false         | -                                                                       |
| legacyHttpVersion | Set this to `true` only for HTTP versions \< 2 in order for SSE to work properly. Can be omitted otherwise.                                                                          | boolean | false     | false         | -                                                                       |
| projectInfo       | Information about the project that contains the process that is being run.                                                                                                           | object  | true      | -             | `{ projectId: '1234-5678-9012' }`                                       |
| locale            | Locale used to localize the application.                                                                                                                                             | string  | false     | en-US         | 'en-US'                                                                 |
| cache             | Caching of CMS resources (cached resources include: theme configurations, substitution tags, enumerations, media library assets)                                                     | boolean | false     | true          | -                                                                       |
| customLoader      | Custom loader components for different loading scenarios                                                                                                                             | object  | false     | -             | `{ startProcess: StartLoaderComponent, saveData: SaveLoaderComponent }` |

<Info>
  When the cache is enabled, these CMS resources are stored in the browser's cache storage, which significantly improves performance and loading times by reducing repeated network requests for the same resources.

  <Tip>
    Environment Recommendations

    * **During Development**: It is recommended to disable caching by setting `[cache]="false"` to ensure you are always working with the latest resources. This prevents outdated assets from being used during active development.
    * **For Production**: Always keep caching enabled (`[cache]="true"`) to maximize performance and optimize resource loading times.
  </Tip>
</Info>

### Data and actions

Custom components will be hydrated with data through the \$data input observable which must be defined in the custom component class.

```typescript theme={"system"}

@Component({
  selector: 'my-custom-component',
  templateUrl: './custom-component.component.html',
  styleUrls: ['./custom-component.component.scss'],
})
export class CustomComponentComponent  {
  data$ = input<Observable<any> | null>(null)
}
```

Component actions are always found under `data` -> `actionsFn` key.

Action names are configurable via the process editor.

```typescript theme={"system"}
# data object example
data: {
    actionsFn: {
      action_one: () => void;
      action_two: () => void;
    }
  }
```

#### Custom component validation

Custom components can validate their own status. We can inject the `FLX_VALIDATOR_SERVICE` service and use it to validate the component. Whe service exposes the following properties:

* `validate(isValid: boolean)` - used to validate the component
* `saveData(data: any)` - used to save data
* `validated$` - used to monitor external submission from the process

Example of the a custom component that validates an input with a required validator:

```ts theme={"system"}
@Component({
  selector: 'flx-custom-validation',
  imports: [CommonModule, ReactiveFormsModule],
  template: `
    Custom validation:
    <input [formControl]="fc" />
    @if (formSubmitted() && fc.invalid) {
      <span>error</span>
    }
  `
})
export class FlxCustomValidationComponent implements OnInit {
  data$ = input<Observable<any> | null>(null) // can be used to get process data & actions

  validationService = inject(FLX_VALIDATOR_SERVICE) // service used to validate the custom component - ony use in components that need validation

  fc = new FormControl('', Validators.required) // the form control has a required validator.
  formSubmitted = signal(false)

  ngOnInit(): void {
    // update validity
    this.fc.statusChanges.subscribe((status) => {
      this.validationService.validate(status === 'VALID')
    })
    // save data
    this.fc.valueChanges.subscribe((value) => {
      this.validationService.saveData({ app: { test1: value, test2: `${value}${value}` } })
    })
    // monitor external submission
    this.validationService.validated$.subscribe(() => {
      this.formSubmitted.set(true)
    })
  }
}

```

### Custom interceptors

* Starting from the FlowX SDKs version 4.6, the Angular `HttpClientModule` is no longer used internally to make HTTP requests. Thus, we have a new mechanism that allows you to create custom interceptors for handling HTTP requests.

#### Request Interceptors

* Here is an example that illustrates how to create an interceptor that adds a custom header to all outgoing requests:

```typescript theme={"system"}
// Import the necessary types
import { FLX_REQUEST_INTERCEPTORS_CONFIG } from '@flowx/angular-sdk'
import { HttpRequestInterceptor } from '@flowx/core-sdk'

// create the interceptor factory function

const customHeaderInterceptor: HttpRequestInterceptor[] = [
  {
    onFulfilled: (response) => {
      response.headers['custom-header'] = 'custom-value'
      return response
    },
  }
]

// Add the interceptor to the providers array in the main app module

{
  provide: FLX_REQUEST_INTERCEPTORS_CONFIG,
  useValue: customHeaderInterceptor,
}
```

#### Response Interceptors

* Here is an example that illustrates how to create an interceptor that shows a message when a response errors out:

```typescript theme={"system"}
import { FLX_RESPONSE_INTERCEPTORS_CONFIG } from '@flowx/angular-sdk'
import { HttpResponseInterceptor } from '@flowx/core-sdk'

const customHErrorInterceptor: HttpResponseInterceptor[] = [
  {
    onRejected: (response) => {
      if (response.status !== 200) {
        console.error('Something went wrong, we should handle this!', response.message)
      }
      return response
    }
  }
]

// Add the interceptor to the providers array in the main app module
{
  provide: FLX_RESPONSE_INTERCEPTORS_CONFIG,
  useValue: customHErrorInterceptor,
}
```

#### Interceptors that use Dependency injection

* If you need to use a service in your interceptor, you can use provider factories coupled with the `deps` property to inject the service into the interceptor:

```typescript theme={"system"}
// the interceptor factory function that receives the custom service as an argument through dependency injection:
const interceptor: (custom: any) => HttpRequestInterceptor[] = (customService: CustomService) => [{
  onFulfilled: (response) => {
    // do something with the custom service
    // interceptor logic
    return response
  }
}]

// Add the interceptor to the providers array in the main app module
{
  provide: FLX_REQUEST_INTERCEPTORS_CONFIG,
  useFactory: (customService: CustomService) => [
    interceptorFactory(customService),
  ],
  deps: [CustomService], // provider factory dependencies
}
```

### Using custom icons

The SDK provides a mechanism for using custom icons. Providers for custom icons should be included in the main app module to be available for the whole app.

```ts theme={"system"}
import { FlxIconModule } from '@flowx/angular-ui-toolkit'

// create a custom dictionary of icons
const customIconDictionary = {
  'custom-icon': 'custom icon svg'
}

// add the custom icon dictionary to the providers array in the main app module.
providers: [
  ...
  importProvidersFrom(FlxIconModule),
  provideExtraIconSet(customIconDictionary),
]
```

### Process end handling

The SDK provides a mechanism for container applications to handle process completion events through the `(processEnd)` output event. This allows you to implement custom logic when a main process reaches an end state, such as redirecting users or triggering cleanup operations.

The `processEnd` event is triggered when the **main process** (not subprocesses) reaches any terminal state:

* `FINISHED` - Process completed successfully
* `FAILED` - Process encountered an error
* `ABORTED` - Process was manually terminated
* Other terminal states

<Info>
  Only the main process triggers this event. Subprocess completions do not trigger the event to avoid unnecessary interruptions during complex process flows.
</Info>

#### Implementation

To handle process end events, bind to the `(processEnd)` output event of the `<flx-process-renderer>` component:

```typescript theme={"system"}
import { Component } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  selector: 'app-process',
  template: `
    <flx-process-renderer
      [apiUrl]="apiUrl"
      [authToken]="authToken"
      [processName]="processName"
      [processStartData]="processStartData"
      [workspaceId]="workspaceId"
      [processApiPath]="processApiPath"
      [themeId]="themeId"
      [projectInfo]="projectInfo"
      (processEnd)="onProcessEnd()"
    />
  `
})
export class ProcessComponent {
  constructor(private router: Router) {}

  onProcessEnd(): void {
    // Your custom logic here
    console.log('Process has ended');
    
    // Example: Redirect to home page
    this.router.navigate(['/dashboard']);
  }
}
```

### Custom loader

The SDK provides a mechanism for container applications to customize the loader UI displayed during process execution. This allows you to replace the default FlowX loader with your own custom implementation based on different loading scenarios.

#### Configuration

To configure custom loaders, add them to the `FlxProcessModule.withConfig()` method in your application module:

```typescript theme={"system"}
import { FlxProcessModule } from '@flowx/angular-sdk';
import { Type } from '@angular/core';

// Define your custom loader components
@Component({
  selector: 'app-start-loader',
  template: `
    <div class="custom-start-loader">
      <div class="spinner"></div>
      <p>Starting process...</p>
    </div>
  `
})
export class StartProcessLoaderComponent {}

@Component({
  selector: 'app-specific-action-loader',
  template: `
    <div class="custom-specific-action-loader">
      <div class="spinner"></div>
      <p>Executing specific action...</p>
    </div>
  `
})
export class SpecificActionLoaderComponent {}

// Register the custom loaders in your app module
@NgModule({
  imports: [
    FlxProcessModule.withConfig({
      customLoader: {
        startProcess: StartProcessLoaderComponent,
        // reloadProcess: ReloadProcessLoaderComponent,
        // defaultAction: DefaultActionLoaderComponent,
        // defaultUpload: DefaultUploadLoaderComponent,
        actions: {
          action1: SpecificActionLoaderComponent,
          // action2: SaveDataLoaderComponent,
        },
      },
      components: {},
      services: {},
    }),
  ],
})
export class AppModule {}
```

#### API Specification

The custom loader configuration accepts an object of type `CustomLoader`:

```typescript theme={"system"}
type CustomLoader = {
  actions?: Record<string, Type<any>>
  startProcess?: Type<any>
  reloadProcess?: Type<any>
  defaultAction?: Type<any>
  defaultUpload?: Type<any>
}
```

##### Loader Types

* **`startProcess`** - Displayed when starting or resuming a process
* **`reloadProcess`** - Displayed when reloading a process
* **`defaultAction`** - Default loader for actions when `loaderType` is `'action'`. Used when no specific action loader is found in the `actions` record
* **`defaultUpload`** - Default loader for file uploads when `loaderType` is `'upload'`
* **`actions`** - Record mapping specific action identifiers to custom loaders. When an action is executed, the SDK will first check for a matching entry in this record before falling back to `defaultAction`

#### Fallback Behavior

<Info>
  If no custom loader is provided for a specific type, the SDK will automatically fall back to the built-in FlowX loader. This ensures your application continues to function even with partial custom loader configuration.
</Info>

<Tip>
  You can use substitution tags and media library assets within your custom loader components to create rich, branded loading experiences that match your application's design system.
</Tip>

### Enumerations and translations

The SDK library provides a mechanism for handling enumerations and translations. The API for the method that handles enumerations is provided by the `getEnumeration` method which is `Promise` based.

<Warning>
  These methods should only be used in custom components and within a process context because internal requests depend on the presence of a running project details.
</Warning>

#### Custom enumerations

```ts theme={"system"}
import {getEnumeration} from '@flowx/angular-sdk'

// get an enumeration by name
const enumeration = await getEnumeration('enumerationName')

// get enumeration with a parent
const enumeration = await getEnumeration('enumerationName', 'parentName')

// get enumerations and cache the result for subsequent calls
const enumerations = await getEnumerations('enumerationName', null, true)
```

#### Translations

The SDK provides a `FlxLocalizePipe` that allows you to manage translations within your application. The pipe is standalone and can be used both in templates and in custom components.

* Here is an example of how to use the pipe in a template:

```ts theme={"system"}
// import the pipe in the module where you want to use it
import { FlxLocalizePipe } from '@flowx/angular-sdk'

imports: [
  ...
  FlxLocalizePipe
]
```

```html theme={"system"}
<!-- use the pipe in the template of a custom component -->
<span>{{ 'hello' | flxLocalize }}</span>
```

* Here is an example of how to use the pipe in a custom component:

```ts theme={"system"}
const localize = new FlxLocalizePipe()
const translatedText = localize.transform('@@substitution_tag')
```

### Analytics

<Info>
  The SDK provides a mechanism for collecting analytics events through a unified `CustomEvent` system. These events can be used to track screens and action events.
</Info>

To use analytics features, make sure you've imported the necessary SDK module:

```ts theme={"system"}
import {
   ANALYTICS_EVENTS,
   AnalyticsData,
   pushAnalyticsData,
} from '@flowx/core-sdk';
```

#### Emitting Analytics Events

Analytics events are dispatched using the `pushAnalyticsData(payload: AnalyticsData)` method. The SDK defines two event types:

```ts theme={"system"}
enum ANALYTICS_EVENTS {
  SCREEN = 'SCREEN',
  ACTION = 'ACTION',
}
```

Each analytics event should be an object of type AnalyticsData:

```ts theme={"system"}
type AnalyticsData = {
  type: ANALYTICS_EVENTS;
  value: string;
  screen?: string;
  component?: string;
  label?: string;
  customPayload?: object;
}
```

<Info>
  The value property represents the identifier set in the process definition.

  For ACTION type events there are some additional properties provided:

  * component - The type of component triggering the action
  * label - The label of the component
  * screen - The identifier of the screen containing the component, if set
</Info>

#### Listening for Analytics Events

You can subscribe to analytics events using the standard CustomEvent API:

```ts theme={"system"}
ngOnInit(): void {
  document.addEventListener('flowx:analytics', this.analyticsListener);
}

analyticsListener = (event: CustomEvent<AnalyticsData>) => {
  console.log('Received flowx:analytics event:', event.detail);
};

ngOnDestroy(): void {
  document.removeEventListener('flowx:analytics', this.analyticsListener);
}

```

<Check> Ensure that you remove the event listener on component destruction to avoid memory leaks. </Check>

#### Custom Payload

This functionality, allowing you to capture and send custom data alongside standard analytics events.

When analytics custom payload is configured in FlowX Designer, the renderer automatically processes variable substitution and includes the resulting data in analytics events.

<Steps>
  <Step title="Receive custom payload configuration">
    The renderer receives the analytics configuration as a JSON string with variable placeholders:

    ```json theme={"system"}
    "analyticsCustomPayload": "{\n \"name\": ${app.input}\n}"
    ```
  </Step>

  <Step title="Process variable substitution">
    The SDK replaces variables with actual values from the process data store:

    <CodeGroup>
      ```json Template theme={"system"}
      {
          "name": "${app.input}",
          "client": "${app.client}",
          "amount": "${app.amount}"
      }
      ```

      ```json Result theme={"system"}
      {
          "name": "john",
          "client": { "id": "123", "name": "John Doe" },
          "amount": 1500
      }
      ```
    </CodeGroup>
  </Step>

  <Step title="Add to analytics event">
    The processed payload is included in the analytics event under the `customPayload` property:

    ```typescript theme={"system"}
    // Analytics event structure with custom payload
    {
        type: 'ACTION', // or 'SCREEN'
        info: {
            value: 'Save personal data',
            screen: 'Personal Data',
            component: 'BUTTON',
            label: 'Save',
            customPayload: {
                name: "john",
                client: { id: "123", name: "John Doe" },
                amount: 1500
            }
        }
    }
    ```
  </Step>
</Steps>

### Caching

The SDK provides a caching mechanism for static resources. The cache is enabled by default and can be disabled by setting the [cache input](../../4.7.x/sdks/angular-renderer#parameters) of the `flx-process-renderer` component to `false`. When turned on, the cache will store the static resources in the browser's cache storage.

<Info>
  Common Scenario: When making updates to CMS resources (like substitution tags or media library images) during development, you may find that after a browser refresh, the changes don't appear.
</Info>

<Warning>
  Important: This issue is most commonly encountered when transitioning from versions before 4.7.x to version 4.7.x or newer, as the caching behavior changed
</Warning>

<Info>
  Common Scenario: When making updates to CMS resources (like substitution tags or media library images) during development, you may find that after a browser refresh, the changes don't appear.
</Info>

<Warning>
  Important: This issue is most commonly encountered when transitioning from versions before 4.7.x to version 4.7.x or newer, as the caching behavior changed
</Warning>

To reset the cache, you can go to the `Application` (Chrome) or `Storage` (Firefox) tab in the browser Dev tools and either clear the cache or disable the cache for the current site.

|   Browser   |  Dev Tools Tab  |                                                                Screenshot                                                                |
| :---------: | :-------------: | :--------------------------------------------------------------------------------------------------------------------------------------: |
|  **Chrome** | Application tab | <Frame caption="Chrome - Application tab">![Chrome Cache](https://s3.eu-west-1.amazonaws.com/docx.flowx.ai/470/chrome_cahce.png)</Frame> |
| **Firefox** |   Storage tab   |  <Frame caption="Firefox - Storage tab">![Firefox Cache](https://s3.eu-west-1.amazonaws.com/docx.flowx.ai/470/firefox_cache.png)</Frame> |

**How to clear the cache**:

* **Chrome**: Navigate to Application → Storage → Cache storage → Right-click on "flowx-resources-cache" → Clear
* **Firefox**: Navigate to Storage → Cache Storage → Right-click → Clear

### Interacting with the process

Data from the process is communicated via the **Server Send Event** protocol under the following keys:

| Name            |                                        Description                                       | Example |   |
| --------------- | :--------------------------------------------------------------------------------------: | :-----: | - |
| Data            |             data updates for process model bound to default/custom components            |         |   |
| ProcessMetadata | updates about process metadata, ex: progress update, data about how to render components |         |   |
| RunAction       |                       instructs the UI to perform the given action                       |         |   |

### Chat component

To use the `FlxChatRendererComponent` component, import the module in your project:

```ts theme={"system"}
import { FlxChatRendererComponent } from '@flowx/angular-sdk';
```

#### Usage

Include the component in your template:

```xml theme={"system"}
<flx-chat-renderer
  [apiUrl]="apiUrl"
  [authToken]="accessToken()"
  [staticAssetsPath]="staticAssetsPath"
  [language]="language()"
  [locale]="locale()"
  [themeId]="themeId()"
  [projectId]="projectId()"
  [workspaceId]="workspaceId()"
  [source]="source()"
  [chatConfig]="parsedChatConfig()"
  [cache]="cache()"
/>
```

Parameters:

| Name               | Description                                   | Type      | Mandatory | Example                           |
| ------------------ | --------------------------------------------- | --------- | --------- | --------------------------------- |
| `apiUrl`           | Your base API URL                             | `string`  | ✅         | `https://yourDomain.dev`          |
| `authToken`        | Authorization token                           | `string`  | ✅         | (retrieved from auth provider)    |
| `staticAssetsPath` | Path for static resources                     | `string`  | ❌         | (set via environment)             |
| `language`         | Language used to localize the chat interface  | `string`  | ❌         | `en`                              |
| `locale`           | Locale setting for date and number formatting | `string`  | ❌         | `en-US`                           |
| `themeId`          | Theme identifier for styling                  | `string`  | ❌         | (retrieved dynamically)           |
| `projectId`        | The FlowX project ID                          | `string`  | ✅         | (retrieved dynamically)           |
| `workspaceId`      | The workspace ID                              | `string`  | ✅         | (retrieved dynamically)           |
| `source`           | Source object with type and id                | `object`  | ✅         | `{ type: 'WORKFLOW', id: '...' }` |
| `chatConfig`       | Chat configuration object                     | `object`  | ❌         | `{ welcomeMessage: '...', ... }`  |
| `cache`            | Enable caching for chat responses             | `boolean` | ❌         | `true`                            |

#### chatConfig parameters

The `chatConfig` object accepts the following properties:

| Name               | Description                                  | Type      | Default value            |
| ------------------ | -------------------------------------------- | --------- | ------------------------ |
| `welcomeMessage`   | Message displayed when chat is first opened  | `string`  | `'Welcome to the chat!'` |
| `thinkingMessage`  | Message displayed while waiting for response | `string`  | `'Thinking...'`          |
| `title`            | Chat window title                            | `string`  | `'Chat'`                 |
| `subtitle`         | Chat window subtitle                         | `string`  | `'Chat subtitle'`        |
| `showChatIcon`     | Whether to display the chat icon             | `boolean` | `true`                   |
| `showSeparator`    | Whether to show separator between messages   | `boolean` | `true`                   |
| `newChatLabel`     | Label for the new chat button                | `string`  | `'New chat'`             |
| `inputPlaceholder` | Placeholder text for the message input field | `string`  | `'Enter your message'`   |
| `maxInputRows`     | Maximum number of rows for the input field   | `number`  | `10`                     |
| `historyTitle`     | Title displayed on the chat history panel    | `string`  | —                        |

### Task management component

The `flx-task-manager` component is available in the `FlxTaskManagementComponent`. To use it, import the required module in your Angular project:

```bash theme={"system"}
import { FlxTasksManagementComponent } from '@flowx/angular-sdk';
```

#### Usage

Include the component in your template:

```xml theme={"system"}
<flx-task-management
      [apiUrl]="apiUrl"
      [authToken]="accessToken"
      [appId]="appId()"
      [language]="language()"
      [themeId]="themeId()"
      [staticAssetsPath]="staticUrl"
      [viewDefinitionId]="viewDefinitionId()"
      [locale]="locale()"
      [buildId]="buildId()"
      [workspaceId]="workspaceId()"
  ></flx-task-management>
```

Parameters:

| Name               | Description                            | Type     | Mandatory | Example                        |
| ------------------ | -------------------------------------- | -------- | --------- | ------------------------------ |
| `apiUrl`           | Endpoint where the tasks are available | `string` | ✅         | `https://yourDomain.dev/tasks` |
| `authToken`        | Authorization token                    | `string` | ✅         | (retrieved from local storage) |
| `appId`            | The application ID                     | `string` | ✅         | (retrieved dynamically)        |
| `viewDefinitionId` | The view configuration identifier      | `string` | ✅         | (retrieved dynamically)        |
| `workspaceId`      | The workspace ID                       | `string` | ✅         | (retrieved dynamically)        |
| `themeId`          | The theme identifier                   | `string` | ❌         | (retrieved dynamically)        |
| `language`         | The selected language                  | `string` | ❌         | (retrieved dynamically)        |
| `locale`           | The localization setting               | `string` | ❌         | (retrieved dynamically)        |
| `buildId`          | The current build identifier           | `string` | ❌         | (retrieved dynamically)        |
| `staticAssetsPath` | Path for static resources              | `string` | ❌         | (set via environment)          |

### Task management public API

The Angular SDK provides a comprehensive public API for building custom task management interfaces.
This API allows you to fetch tasks, manage comments, handle task actions, and interact with task data programmatically.

#### Importing the Service

To use the task management public API, inject the `PublicTasksService` from `@flowx/angular-sdk`:

```typescript theme={"system"}
import { PublicTasksService } from '@flowx/angular-sdk';
import { inject } from '@angular/core';

export class MyComponent {
  private taskService = inject(PublicTasksService);
}
```

#### Available Types

The Angular SDK exports the following types for task management:

```typescript theme={"system"}
import {
  PublicTasksService,
  TMView,
  TMViewTask,
  TMViewColumn,
  TMTaskComment,
  TMTaskHistory,
  TMUser,
  TMEnumerations,
  TMFilterOperators,
  TMFilters,
  TMSort,
  TMPaginatedResponse,
  TMSetupOptions,
  TMExecuteTaskActions,
  TMOperatorsType,
} from '@flowx/angular-sdk';
```

#### Initialization

Before using the task management API, you need to initialize the task manager resources. This fetches the view configuration, enumerations, and filter operators.

```typescript theme={"system"}
this.taskService.getTaskManagerResources({
  apiUrl: 'https://yourDomain.dev/tasks',
  authToken: 'your-auth-token',
  appInfo: { appId: 'app-123' },
  viewId: 'view-456',
  workspaceId: 'workspace-789',
  themeId: 'theme-012', // Optional
  language: 'en', // Optional
  locale: 'en-US', // Optional
  buildId: 'build-345', // Optional
  staticAssetsPath: '/static', // Optional
}).subscribe(({ view, enumerations, filterOperators }) => {
  // Use the view, enumerations, and filterOperators
});
```

**Parameters:**

| Name               | Description                                     | Type                | Mandatory | Example                        |
| ------------------ | ----------------------------------------------- | ------------------- | --------- | ------------------------------ |
| `apiUrl`           | Endpoint where the tasks are available          | `string`            | ✅         | `https://yourDomain.dev/tasks` |
| `authToken`        | Authorization token                             | `string`            | ✅         | (retrieved from local storage) |
| `appInfo`          | Application information object containing appId | `{ appId: string }` | ✅         | `{ appId: "app-123" }`         |
| `viewId`           | The view configuration identifier               | `string`            | ✅         | (retrieved dynamically)        |
| `workspaceId`      | The workspace ID                                | `string`            | ✅         | (retrieved dynamically)        |
| `themeId`          | The theme identifier                            | `string`            | ❌         | (retrieved dynamically)        |
| `language`         | The selected language                           | `string`            | ❌         | `"en"`                         |
| `locale`           | The localization setting                        | `string`            | ❌         | `"en-US"`                      |
| `buildId`          | The current build identifier                    | `string`            | ❌         | (retrieved dynamically)        |
| `staticAssetsPath` | Path for static resources                       | `string`            | ❌         | (set via environment)          |

**Returns:** Observable that emits an object containing:

* `view`: The view configuration object (`TMView`)
* `enumerations`: Available enumeration options for filters (`TMEnumerations`)
* `filterOperators`: Available filter operators for each column (`TMFilterOperators`)

#### Fetching Tasks

##### `getViewTasks`

Fetches tasks for a specific view with support for sorting, filtering, pagination, and search.

```typescript theme={"system"}
this.taskService.getViewTasks(
  page,      // Page number (0-based)
  sort,      // Array of sort configurations
  filters,   // Array of filter configurations
  keyword,   // Search string
  size       // Page size
).subscribe((response) => {
  const tasks = response.content; // Array of TMViewTask objects
});
```

**Parameters:**

| Name      | Description                    | Type          | Mandatory | Example                                       |
| --------- | ------------------------------ | ------------- | --------- | --------------------------------------------- |
| `page`    | Page number (0-based)          | `number`      | ✅         | `0`                                           |
| `sort`    | Array of sort configurations   | `TMSort[]`    | ✅         | `[{ keyName: "priority", direction: "ASC" }]` |
| `filters` | Array of filter configurations | `TMFilters[]` | ✅         | See filter examples below                     |
| `keyword` | Search string for task search  | `string`      | ✅         | `"urgent"`                                    |
| `size`    | Number of items per page       | `number`      | ✅         | `10`                                          |

**Returns:** Observable that emits a `TMPaginatedResponse<TMViewTask>` containing:

* `content`: Array of `TMViewTask` objects
* `totalElements`: Total number of tasks
* `totalPages`: Total number of pages
* Other pagination metadata

##### `getViewTask`

Fetches a specific task by ID and token UUID.

```typescript theme={"system"}
this.taskService.getViewTask(taskId, tokenUuid)
  .subscribe((task) => {
    // Use the task
  });
```

**Parameters:**

| Name        | Description                         | Type     | Mandatory | Example            |
| ----------- | ----------------------------------- | -------- | --------- | ------------------ |
| `taskId`    | The unique task ID                  | `string` | ✅         | `"task-123"`       |
| `tokenUuid` | The token UUID associated with task | `string` | ✅         | `"token-uuid-456"` |

**Returns:** Observable that emits a `TMViewTask` object.

#### Task Details

##### `getTaskComments`

Fetches all comments for a specific task.

```typescript theme={"system"}
this.taskService.getTaskComments(taskId)
  .subscribe((comments) => {
    // Use the comments array
  });
```

**Parameters:**

| Name     | Description        | Type     | Mandatory | Example      |
| -------- | ------------------ | -------- | --------- | ------------ |
| `taskId` | The unique task ID | `string` | ✅         | `"task-123"` |

**Returns:** Observable that emits an array of `TMTaskComment` objects.

##### `getTaskHistory`

Fetches the history/audit trail for a specific task.

```typescript theme={"system"}
this.taskService.getTaskHistory(taskId)
  .subscribe((history) => {
    // Use the history array
  });
```

**Parameters:**

| Name     | Description        | Type     | Mandatory | Example      |
| -------- | ------------------ | -------- | --------- | ------------ |
| `taskId` | The unique task ID | `string` | ✅         | `"task-123"` |

**Returns:** Observable that emits an array of `TMTaskHistory` objects.

##### `getAssignees`

Fetches available assignees for a task, with optional search filtering.

```typescript theme={"system"}
this.taskService.getAssignees(task, { keyword: 'john' })
  .subscribe((users) => {
    // Use the users array
  });
```

**Parameters:**

| Name    | Description     | Type                  | Mandatory | Example               |
| ------- | --------------- | --------------------- | --------- | --------------------- |
| `task`  | The task object | `TMViewTask`          | ✅         | (task object)         |
| `query` | Search options  | `{ keyword: string }` | ✅         | `{ keyword: "john" }` |

**Note:** The keyword must be at least 4 characters long. If shorter, the Observable will emit an error.

**Returns:** Observable that emits an array of `TMUser` objects.

##### `getBulkAssignees`

Fetches available assignees for multiple tasks in bulk.

```typescript theme={"system"}
this.taskService.getBulkAssignees(
  [{ id: 'task-1', tokenUuid: 'token-1' }, { id: 'task-2', tokenUuid: 'token-2' }],
  { keyword: 'john' }
).subscribe((users) => {
  // Use the users array
});
```

**Parameters:**

| Name    | Description                                 | Type                                  | Mandatory | Example                                    |
| ------- | ------------------------------------------- | ------------------------------------- | --------- | ------------------------------------------ |
| `tasks` | Array of task objects with id and tokenUuid | `{ id: string; tokenUuid: string }[]` | ✅         | `[{ id: "task-1", tokenUuid: "token-1" }]` |
| `query` | Search options                              | `{ keyword: string }`                 | ✅         | `{ keyword: "john" }`                      |

**Returns:** Observable that emits an array of `TMUser` objects.

#### Task Actions

##### `executeTaskAction`

Executes an action on a specific task (e.g., assign, complete, cancel).

```typescript theme={"system"}
this.taskService.executeTaskAction(action, task, payload)
  .subscribe(() => {
    // Action completed
  });
```

**Parameters:**

| Name      | Description                                    | Type                   | Mandatory | Example              |
| --------- | ---------------------------------------------- | ---------------------- | --------- | -------------------- |
| `action`  | The action to execute                          | `TMExecuteTaskActions` | ✅         | `TaskActions.ASSIGN` |
| `task`    | The task object                                | `TMViewTask`           | ✅         | (task object)        |
| `payload` | Additional payload (e.g., username for assign) | `any`                  | ❌         | `"john.doe"`         |

**Available Actions:**

* `TaskActions.ASSIGN` - Assign task to a user
* `TaskActions.COMPLETE` - Mark task as complete
* `TaskActions.CANCEL` - Cancel the task
* `TaskActions.CHANGE_PRIORITY` - Change task priority
* `TaskActions.VIEW` - View task details

##### `bulkUpdate`

Applies an action to multiple tasks at once.

```typescript theme={"system"}
this.taskService.bulkUpdate(
  [{ id: 'task-1', tokenUuid: 'token-1' }, { id: 'task-2', tokenUuid: 'token-2' }],
  TaskActions.COMPLETE,
  'username' // Optional, for assign action
).subscribe(() => {
  // Bulk action completed
});
```

**Parameters:**

| Name       | Description                                 | Type                                  | Mandatory | Example                                    |
| ---------- | ------------------------------------------- | ------------------------------------- | --------- | ------------------------------------------ |
| `tasks`    | Array of task objects with id and tokenUuid | `{ id: string; tokenUuid: string }[]` | ✅         | `[{ id: "task-1", tokenUuid: "token-1" }]` |
| `action`   | The action to execute                       | `TMExecuteTaskActions`                | ✅         | `TaskActions.COMPLETE`                     |
| `username` | Username for assign action                  | `string`                              | ❌         | `"john.doe"`                               |

**Returns:** Observable that completes when the bulk action is done.

##### `updatePriority`

Updates the priority of a specific task.

```typescript theme={"system"}
this.taskService.updatePriority(taskId, priority)
  .subscribe(() => {
    // Priority updated
  });
```

**Parameters:**

| Name       | Description        | Type     | Mandatory | Example      |
| ---------- | ------------------ | -------- | --------- | ------------ |
| `taskId`   | The unique task ID | `string` | ✅         | `"task-123"` |
| `priority` | New priority value | `number` | ✅         | `5`          |

**Returns:** Observable that completes when the priority is updated.

#### Comments Management

##### `addComment`

Adds a new comment to a task.

```typescript theme={"system"}
this.taskService.addComment(taskId, { message: 'New comment text' })
  .subscribe((comment) => {
    // Comment added, use the returned comment
  });
```

**Parameters:**

| Name      | Description         | Type                  | Mandatory | Example                           |
| --------- | ------------------- | --------------------- | --------- | --------------------------------- |
| `taskId`  | The unique task ID  | `string`              | ✅         | `"task-123"`                      |
| `comment` | Comment data object | `{ message: string }` | ✅         | `{ message: "New comment text" }` |

**Returns:** Observable that emits the created `TMTaskComment` object.

##### `deleteComment`

Removes a comment from a task.

```typescript theme={"system"}
this.taskService.deleteComment(taskId, commentId)
  .subscribe(() => {
    // Comment deleted
  });
```

**Parameters:**

| Name        | Description           | Type     | Mandatory | Example         |
| ----------- | --------------------- | -------- | --------- | --------------- |
| `taskId`    | The unique task ID    | `string` | ✅         | `"task-123"`    |
| `commentId` | The unique comment ID | `string` | ✅         | `"comment-456"` |

**Returns:** Observable that completes when the comment is deleted.

#### Service State Management

##### `getView`

Gets the current view configuration.

```typescript theme={"system"}
const view = this.taskService.getView();
```

**Returns:** The current `TMView` object or `null` if not initialized.

##### `getEnumerations`

Gets the current enumerations.

```typescript theme={"system"}
const enumerations = this.taskService.getEnumerations();
```

**Returns:** The current `TMEnumerations` object.

##### `setView`

Sets the view configuration manually.

```typescript theme={"system"}
this.taskService.setView(view, format);
```

**Parameters:**

| Name     | Description                   | Type      | Mandatory | Example       |
| -------- | ----------------------------- | --------- | --------- | ------------- |
| `view`   | The view configuration object | `TMView`  | ✅         | (view object) |
| `format` | Whether to format the view    | `boolean` | ❌         | `false`       |

#### Real-time Updates (SSE)

##### `initSse`

Initializes a Server-Sent Events (SSE) connection for real-time task updates.

```typescript theme={"system"}
this.taskService.initSse();
```

**Note:** This should be called after initializing the task manager resources with `getTaskManagerResources()`.

##### `getSseEvents`

Gets an Observable stream of SSE events.

```typescript theme={"system"}
this.taskService.getSseEvents()
  .subscribe((event) => {
    // Handle SSE event
    console.log('SSE event:', event);
  });
```

**Returns:** Observable that emits `MessageEvent<string>` objects.

##### `closeSseConnection`

Closes the SSE connection.

```typescript theme={"system"}
ngOnDestroy(): void {
  this.taskService.closeSseConnection();
}
```

**Note:** Always close the SSE connection when your component is destroyed to prevent memory leaks.

## Coding style tests

Always follow the Angular official [coding styles](https://angular.io/guide/styleguide).

Below you find a Storybook which demonstrates how components behave under different states, props, and conditions, it allows you to preview and interact with individual UI components in isolation, without the need for a full-fledged application:

<Card title="Storybook" href="https://storybooks.flowxai.dev/" icon="book" />


## Related topics

- [Renderer SDKs](/release-notes/v4.x/v4.6.x/v4.6.0-january-2025/migrating-from-v4.1.x-to-v4.6.0/renderers.md)
- [SDKs overview](/5.1/sdks/sdks-overview.md)
- [FlowX.AI 4.6.0 Release Notes](/release-notes/v4.x/v4.6.x/v4.6.0-january-2025/v4.6.0-january-2025.md)
