Skip to main content

Usage

This guide covers the essential patterns and practices for using FlowX.AI UI Toolkit components in your Angular or React application. Learn how to integrate process-driven components, handle data binding, and manage component lifecycle.

Core concepts

FlowX.AI UI Toolkit components connect your frontend directly to FlowX.AI process definitions. Understanding these core concepts helps you build effective process-driven applications:

Process container

The process container is the root component that manages a FlowX.AI process instance. It handles:
  • Process initialization and lifecycle
  • Communication with the FlowX.AI platform
  • State management and data synchronization
  • Navigation between process steps

Component data binding

Components automatically bind to process data defined in your process model. Data flows bidirectionally:
  • Process to UI: Process variables populate component values
  • UI to Process: User interactions update process variables

Process actions

User interactions trigger process actions that advance the workflow:
  • Button clicks execute process transitions
  • Form submissions validate and save data
  • Custom actions trigger business logic

Using the process container

The process container is your entry point for rendering FlowX.AI processes.
process-view.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-process-view',
  template: `
    <div class="process-wrapper">
      <flx-process-container
        [processName]="processName"
        [processStartData]="startData"
        (processStarted)="onProcessStarted($event)"
        (processCompleted)="onProcessCompleted($event)"
        (processError)="onProcessError($event)"
      >
      </flx-process-container>
    </div>
  `,
  styles: [`
    .process-wrapper {
      padding: 20px;
      max-width: 1200px;
      margin: 0 auto;
    }
  `]
})
export class ProcessViewComponent implements OnInit {
  processName = 'customer-onboarding';
  startData: any = {};
  
  constructor(private route: ActivatedRoute) {}
  
  ngOnInit() {
    // Get initial data from route parameters
    this.route.queryParams.subscribe(params => {
      this.startData = {
        customerId: params['customerId'],
        source: params['source'] || 'web'
      };
    });
  }
  
  onProcessStarted(event: any) {
    console.log('Process started:', event.processInstanceId);
  }
  
  onProcessCompleted(event: any) {
    console.log('Process completed:', event);
    // Navigate to success page or show confirmation
  }
  
  onProcessError(error: any) {
    console.error('Process error:', error);
    // Show error message to user
  }
}

Working with form components

Form components bind to process variables and handle validation automatically.
customer-form.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-customer-form',
  template: `
    <form flxForm>
      <flx-input
        name="firstName"
        label="First Name"
        [required]="true"
        [minLength]="2"
        [maxLength]="50"
      >
      </flx-input>
      
      <flx-input
        name="lastName"
        label="Last Name"
        [required]="true"
      >
      </flx-input>
      
      <flx-input
        name="email"
        label="Email Address"
        type="email"
        [required]="true"
        [pattern]="emailPattern"
      >
      </flx-input>
      
      <flx-select
        name="country"
        label="Country"
        [options]="countries"
        [required]="true"
      >
      </flx-select>
      
      <flx-datepicker
        name="dateOfBirth"
        label="Date of Birth"
        [maxDate]="maxBirthDate"
      >
      </flx-datepicker>
      
      <flx-button
        type="submit"
        label="Continue"
        actionName="CONTINUE"
      >
      </flx-button>
    </form>
  `
})
export class CustomerFormComponent {
  emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
  
  countries = [
    { value: 'US', label: 'United States' },
    { value: 'UK', label: 'United Kingdom' },
    { value: 'CA', label: 'Canada' },
    { value: 'DE', label: 'Germany' }
  ];
  
  maxBirthDate = new Date(); // Today
}
Form field names must match the process variable names defined in your FlowX.AI process model. The toolkit automatically handles data binding between the UI and process state.

Displaying process data

Use display components to show read-only process data.
order-summary.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-order-summary',
  template: `
    <div class="summary-card">
      <h2>Order Summary</h2>
      
      <flx-text
        name="orderNumber"
        label="Order Number"
        [bold]="true"
      >
      </flx-text>
      
      <flx-text
        name="orderDate"
        label="Order Date"
        format="date"
      >
      </flx-text>
      
      <flx-text
        name="totalAmount"
        label="Total Amount"
        format="currency"
        [currency]="'USD'"
      >
      </flx-text>
      
      <flx-table
        name="orderItems"
        [columns]="itemColumns"
      >
      </flx-table>
      
      <flx-status-badge
        name="orderStatus"
        [statusMap]="statusColors"
      >
      </flx-status-badge>
    </div>
  `
})
export class OrderSummaryComponent {
  itemColumns = [
    { field: 'name', header: 'Item Name' },
    { field: 'quantity', header: 'Quantity' },
    { field: 'price', header: 'Price', format: 'currency' }
  ];
  
  statusColors = {
    'pending': 'warning',
    'processing': 'info',
    'completed': 'success',
    'cancelled': 'error'
  };
}

Handling process actions

Buttons and other interactive components trigger process actions.
action-buttons.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-action-buttons',
  template: `
    <div class="action-bar">
      <flx-button
        label="Save Draft"
        actionName="SAVE_DRAFT"
        variant="secondary"
        (actionExecuted)="onDraftSaved($event)"
      >
      </flx-button>
      
      <flx-button
        label="Cancel"
        actionName="CANCEL"
        variant="text"
        [confirm]="{
          title: 'Cancel Process',
          message: 'Are you sure you want to cancel? All changes will be lost.'
        }"
      >
      </flx-button>
      
      <flx-button
        label="Submit"
        actionName="SUBMIT"
        variant="primary"
        [disabled]="!formValid"
        [loading]="isSubmitting"
      >
      </flx-button>
    </div>
  `
})
export class ActionButtonsComponent {
  formValid = false;
  isSubmitting = false;
  
  onDraftSaved(event: any) {
    console.log('Draft saved:', event);
    // Show success message
  }
}

Conditional rendering

Show or hide components based on process state.
conditional-content.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-conditional-content',
  template: `
    <div>
      <flx-conditional
        [when]="'applicationType'"
        [equals]="'individual'"
      >
        <app-individual-form></app-individual-form>
      </flx-conditional>
      
      <flx-conditional
        [when]="'applicationType'"
        [equals]="'business'"
      >
        <app-business-form></app-business-form>
      </flx-conditional>
      
      <flx-conditional
        [when]="'hasErrors'"
        [equals]="true"
      >
        <flx-alert type="error" message="Please correct the errors above.">
        </flx-alert>
      </flx-conditional>
    </div>
  `
})
export class ConditionalContentComponent {}

Component lifecycle hooks

React to component and process lifecycle events.
lifecycle-example.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { FlowxProcessService } from '@flowx/angular-ui-toolkit';
import { Subject, takeUntil } from 'rxjs';

@Component({
  selector: 'app-lifecycle-example',
  template: `<flx-process-container [processName]="processName"></flx-process-container>`
})
export class LifecycleExampleComponent implements OnInit, OnDestroy {
  processName = 'my-process';
  private destroy$ = new Subject<void>();
  
  constructor(private flowxProcess: FlowxProcessService) {}
  
  ngOnInit() {
    // Subscribe to process state changes
    this.flowxProcess.processState$
      .pipe(takeUntil(this.destroy$))
      .subscribe(state => {
        console.log('Process state changed:', state);
      });
    
    // Subscribe to process data changes
    this.flowxProcess.processData$
      .pipe(takeUntil(this.destroy$))
      .subscribe(data => {
        console.log('Process data updated:', data);
      });
  }
  
  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }
}

Best practices

Follow these patterns for optimal component usage:
  • Match field names: Ensure component name props match process variable names exactly
  • Handle errors gracefully: Always implement error handlers for process operations
  • Use TypeScript: Leverage type definitions for better development experience
  • Validate early: Use client-side validation to provide immediate feedback
  • Keep components focused: Break complex forms into smaller, reusable components
  • Test with real data: Use actual process instances during development

Next steps

Theming guide

Customize component appearance to match your brand

Best practices

Production-ready patterns and recommendations

Build docs developers (and LLMs) love