@teamvortexsoftware/vortex-angular-14
v0.0.16
Published
Vortex Components
Readme
Vortex Angular Component
High-performance Angular component for Vortex invitations with seamless integration for Angular 14
🚀 Quick Start
npm install @teamvortexsoftware/vortex-angular-14Basic Usage
import { Component } from '@angular/core';
import { VortexInvite } from '@teamvortexsoftware/vortex-angular-14';
@Component({
selector: 'app-my-component',
standalone: true,
imports: [VortexInvite],
template: `
<vortex-invite
[componentId]="componentId"
[jwt]="jwt"
[isLoading]="isLoading"
[scope]="workspace.id"
[scopeType]="'workspace'"
(invite)="handleInvite($event)"
></vortex-invite>
`,
})
export class MyComponent {
componentId = 'my-widget';
jwt = 'eyJhbGciOiJIUzI1NiIs...';
isLoading = false;
workspace = { id: 'ws-123', name: 'Engineering' };
handleInvite(data: any) {
console.log('Invitation sent:', data);
}
}Module-Based Usage (Angular 14)
import { NgModule } from '@angular/core';
import { VortexInvite } from '@teamvortexsoftware/vortex-angular-14';
@NgModule({
imports: [VortexInvite],
declarations: [MyComponent],
})
export class MyModule {}
@Component({
selector: 'app-my-component',
template: `
<vortex-invite
[componentId]="componentId"
[jwt]="jwt"
[isLoading]="isLoading"
[scope]="workspace.id"
[scopeType]="'workspace'"
(invite)="handleInvite($event)"
></vortex-invite>
`,
})
export class MyComponent {
componentId = 'my-widget';
jwt = 'eyJhbGciOiJIUzI1NiIs...';
isLoading = false;
workspace = { id: 'ws-123', name: 'Engineering' };
handleInvite(data: any) {
console.log('Invitation sent:', data);
}
}📋 Component API Reference
Inputs
| Prop | Type | Required | Description | Docs |
| ------------------------- | ------------------------ | -------- | ------------------------------- | ------------------------------------------------------------------------------------------- |
| componentId | string | ✅ | Component identifier | docs |
| jwt | string | ✅ | JWT token for authentication | docs |
| scope | string | ✅ | Scope identifier (e.g., team ID)| docs |
| scopeType | string | ✅ | Scope type (e.g., "team") | docs |
| isLoading | boolean | ❌ | Loading state indicator | docs |
| onEvent | function | ❌ | Event handler for widget events | docs |
| onSubmit | function | ❌ | Form submission handler | |
| onInvite | function | ❌ | Invitation completion handler | docs |
| onError | function | ❌ | Error handler | |
| emailValidationFunction | function | ❌ | Custom email validation | docs |
| analyticsSegmentation | Record<string, any> | ❌ | Analytics tracking data | |
| userEmailsInGroup | string[] | ❌ | Pre-populated email list | docs |
| templateVariables | Record<string, string> | ❌ | Template variables | docs |
| googleAppClientId | string | ❌ | Google integration client ID | docs |
| googleAppApiKey | string | ❌ | Google integration API key | docs |
| |
Outputs
| Output | Type | Description |
| -------- | ---------------------------------------------- | ------------------------------- |
| ready | EventEmitter<CustomEvent> | Emitted when component is ready |
| submit | EventEmitter<{ formData: any; result: any }> | Emitted on form submission |
| invite | EventEmitter<any> | Emitted when invitation is sent |
| error | EventEmitter<any> | Emitted on error |
| event | EventEmitter<any> | Emitted for widget events |
📖 Advanced Examples
With Custom Event Handlers
import { Component } from '@angular/core';
import { VortexInvite } from '@teamvortexsoftware/vortex-angular-14';
@Component({
selector: 'app-advanced-invite',
standalone: true,
imports: [VortexInvite],
template: `
<vortex-invite
[componentId]="'advanced-widget'"
[jwt]="jwt"
[isLoading]="isLoading"
[scope]="'team-123'"
[scopeType]="'team'"
(invite)="onInvite($event)"
(error)="onError($event)"
(event)="onEvent($event)"
></vortex-invite>
`,
})
export class AdvancedInviteComponent {
jwt = '...';
isLoading = false;
onInvite(data: any) {
console.log('Invitation sent:', data);
this.trackAnalyticsEvent('invitation_sent', data);
}
onError(error: any) {
console.error('Invitation error:', error);
this.showErrorToast(error.message);
}
onEvent(event: any) {
console.log('Widget event:', event);
}
trackAnalyticsEvent(eventName: string, data: any) {
// Your analytics implementation
}
showErrorToast(message: string) {
// Your toast implementation
}
}With Custom Email Validation
import { Component } from '@angular/core';
import { VortexInvite } from '@teamvortexsoftware/vortex-angular-14';
import { EmailGroupMembershipCheckFunction } from '@teamvortexsoftware/vortex-types';
@Component({
selector: 'app-validated-invite',
standalone: true,
imports: [VortexInvite],
template: `
<vortex-invite
[componentId]="'validated-widget'"
[jwt]="jwt"
[scope]="'team-123'"
[scopeType]="'team'"
[emailValidationFunction]="emailValidator"
(invite)="handleInvite($event)"
></vortex-invite>
`,
})
export class ValidatedInviteComponent {
jwt = '...';
emailValidator: EmailGroupMembershipCheckFunction = async (emails: string[]) => {
const isValid = await this.validateEmailsInSystem(emails);
return {
isValid,
errorMessage: isValid ? undefined : 'Emails not found in system',
};
};
async validateEmailsInSystem(emails: string[]): Promise<boolean> {
// Your validation logic
return true;
}
handleInvite(data: any) {
console.log('Invitation sent:', data);
}
}With Template Variables
import { Component } from '@angular/core';
import { VortexInvite } from '@teamvortexsoftware/vortex-angular-14';
@Component({
selector: 'app-templated-invite',
standalone: true,
imports: [VortexInvite],
template: `
<vortex-invite
[componentId]="'templated-widget'"
[jwt]="jwt"
[scope]="'team-123'"
[scopeType]="'team'"
[templateVariables]="templateVars"
(invite)="handleInvite($event)"
></vortex-invite>
`,
})
export class TemplatedInviteComponent {
jwt = '...';
templateVars = {
companyName: 'Acme Corp',
userName: 'John Doe',
customMessage: 'Join our team!',
};
handleInvite(data: any) {
console.log('Invitation sent:', data);
}
}With Analytics Segmentation
import { Component } from '@angular/core';
import { VortexInvite } from '@teamvortexsoftware/vortex-angular-14';
@Component({
selector: 'app-analytics-invite',
standalone: true,
imports: [VortexInvite],
template: `
<vortex-invite
[componentId]="'analytics-widget'"
[jwt]="jwt"
[scope]="'team-123'"
[scopeType]="'team'"
[analyticsSegmentation]="analyticsData"
(invite)="handleInvite($event)"
></vortex-invite>
`,
})
export class AnalyticsInviteComponent {
jwt = '...';
analyticsData = {
source: 'dashboard',
campaign: 'summer-2024',
userType: 'premium',
};
handleInvite(data: any) {
console.log('Invitation sent with analytics:', data);
}
}With Google Contacts Integration
import { Component } from '@angular/core';
import { VortexInvite } from '@teamvortexsoftware/vortex-angular-14';
@Component({
selector: 'app-google-invite',
standalone: true,
imports: [VortexInvite],
template: `
<vortex-invite
[componentId]="'google-widget'"
[jwt]="jwt"
[scope]="'team-123'"
[scopeType]="'team'"
[googleAppClientId]="googleClientId"
[googleAppApiKey]="googleApiKey"
(invite)="handleInvite($event)"
></vortex-invite>
`,
})
export class GoogleInviteComponent {
jwt = '...';
googleClientId = 'your-google-client-id';
googleApiKey = 'your-google-api-key';
handleInvite(data: any) {
console.log('Invitation sent from Google Contacts:', data);
}
}Module-Based with Services (Angular 14)
import { Component, Injectable } from '@angular/core';
import { VortexInvite } from '@teamvortexsoftware/vortex-angular-14';
import { Observable } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class AuthService {
getJWT(): Observable<string> {
// Your JWT retrieval logic
}
}
@Component({
selector: 'app-service-invite',
template: `
<vortex-invite
*ngIf="jwt$ | async as jwt"
[componentId]="'service-widget'"
[jwt]="jwt"
[isLoading]="isLoading"
(invite)="handleInvite($event)"
></vortex-invite>
`,
})
export class ServiceInviteComponent {
jwt$ = this.authService.getJWT();
isLoading = false;
constructor(private authService: AuthService) {}
handleInvite(data: any) {
console.log('Invitation sent:', data);
}
}🛠️ TypeScript Support
Full TypeScript support with exported types:
import { VortexInvite } from '@teamvortexsoftware/vortex-angular-14';
import type { EmailGroupMembershipCheckFunction } from '@teamvortexsoftware/vortex-types';
@Component({
selector: 'app-typed-invite',
standalone: true,
imports: [VortexInvite],
template: `
<vortex-invite
[componentId]="componentId"
[jwt]="jwt"
[scope]="'team-123'"
[scopeType]="'team'"
[emailValidationFunction]="validator"
></vortex-invite>
`,
})
export class TypedInviteComponent {
componentId: string = 'my-widget';
jwt: string = '...';
validator: EmailGroupMembershipCheckFunction = async (emails) => {
return { isValid: true };
};
}🚨 Error Handling
The component gracefully handles all scenarios:
- ✅ Component Ready: Waits for web component to be defined before syncing props
- ✅ Missing Props: Safe defaults applied for optional properties
- ✅ Validation Errors: Emitted through the
erroroutput - ✅ Network Errors: Handled internally with error emission
Error Handling Example
@Component({
selector: 'app-error-handling',
standalone: true,
imports: [VortexInvite, CommonModule],
template: `
<vortex-invite
[componentId]="componentId"
[jwt]="jwt"
(error)="handleError($event)"
(invite)="handleSuccess($event)"
></vortex-invite>
<div class="error-toast" *ngIf="errorMessage">{{ errorMessage }}</div>
`,
})
export class ErrorHandlingComponent {
componentId = 'my-widget';
jwt = '...';
errorMessage = '';
handleError(error: any) {
this.errorMessage = error?.message || 'An error occurred';
console.error('Widget error:', error);
// Clear error after 5 seconds
setTimeout(() => {
this.errorMessage = '';
}, 5000);
}
handleSuccess(data: any) {
this.errorMessage = '';
console.log('Success:', data);
}
}🔧 Best Practices
1. Standalone Components (Recommended for Angular 14+)
import { Component } from '@angular/core';
import { VortexInvite } from '@teamvortexsoftware/vortex-angular-14';
@Component({
selector: 'app-invite',
standalone: true,
imports: [VortexInvite],
template: `
<vortex-invite
[componentId]="componentId"
[jwt]="jwt"
(invite)="handleInvite($event)"
></vortex-invite>
`,
})
export class InviteComponent {
componentId = 'my-widget';
jwt = '...';
handleInvite(data: any) {
console.log('Invitation sent:', data);
}
}2. Module-Based (Traditional Angular 14)
import { NgModule } from '@angular/core';
import { VortexInvite } from '@teamvortexsoftware/vortex-angular-14';
@NgModule({
imports: [VortexInvite],
declarations: [MyComponent],
})
export class MyModule {}3. With RxJS Observables
import { Component } from '@angular/core';
import { VortexInvite } from '@teamvortexsoftware/vortex-angular-14';
import { CommonModule } from '@angular/common';
import { BehaviorSubject } from 'rxjs';
@Component({
selector: 'app-reactive-invite',
standalone: true,
imports: [VortexInvite, CommonModule],
template: `
<vortex-invite
[componentId]="componentId$ | async"
[jwt]="jwt$ | async"
[isLoading]="isLoading$ | async"
[scope]="(scope$ | async)"
[scopeType]="(scopeType$ | async)"
(invite)="handleInvite($event)"
></vortex-invite>
`,
})
export class ReactiveInviteComponent {
componentId$ = new BehaviorSubject('my-widget');
jwt$ = new BehaviorSubject('...');
isLoading$ = new BehaviorSubject(false);
scope$ = new BehaviorSubject('team-123')
scopeType$ = new BehaviorSubject('team');
handleInvite(data: any) {
console.log('Invitation sent:', data);
this.isLoading$.next(false);
}
}🔍 Change Detection
The component uses ChangeDetectionStrategy.OnPush for optimal performance and automatically syncs props when inputs change. In Angular 14, the ChangeDetectorRef is explicitly used to trigger change detection when mounting the component.
🎯 Key Features
- 🎯 Standalone Component - Works with Angular 14+ standalone components
- 📦 Module Compatible - Also works with traditional NgModule architecture
- 🔄 Automatic Prop Syncing - Inputs are automatically synced to the web component
- ⚡ OnPush Change Detection - Optimized performance with explicit change detection
- 🛡️ Type Safety - Full TypeScript support with exported types
- 🚀 Lazy Loading - Web component is loaded on-demand
- 📦 Zero Configuration - Works out of the box
- 🔒 Safe Imports - CUSTOM_ELEMENTS_SCHEMA for web component support
📦 What's Included
- Angular 14+ compatible component wrapper
- Web component bundled inline (no separate script loading needed)
- Full TypeScript definitions
- Support for all widget features:
- Email invitations
- Group management
- Custom validation
- Analytics tracking
- Template variables
- Google Contacts integration
Angular 14 Specifics
- Supports both standalone components and traditional NgModule architecture
- Uses explicit
ChangeDetectorRef.detectChanges()for OnPush strategy - Compatible with Angular 14's Ivy renderer
- Works with RxJS 7.5+ observables
Need help? Contact support or check the documentation at docs.vortex.software.
