Angular Integration Guide
Install IssueCapture in Angular
Add bug reporting to your Angular application in 5 minutes. Works with Angular 15+, TypeScript, and standalone components.
Quick Summary
- Time: 2-5 minutes (7 simple steps)
- Prerequisites: Angular 15+, TypeScript, Jira account, IssueCapture account (free)
- Method: Script tag in index.html or programmatic ngOnInit
- Works with: Angular 15+, Angular Router, NgRx, RxJS
- Bundle size: 32KB initial (152KB for screenshot & annotation tools, lazy-loaded)
Prerequisites
- Angular 15 or higher
- TypeScript 4.9+
- Jira Cloud account (Software or JSM)
- IssueCapture account (sign up free)
Step-by-Step Installation
1
Get Your API Key
Sign up for IssueCapture and retrieve your widget API key from the dashboard
- Go to https://issuecapture.com/signup and create a free account
- Connect your Jira instance via OAuth
- Navigate to the Widgets page and create a new widget
- Copy your API key (starts with "ic_")
2
Add Environment Variable
Store your API key in your environment configuration
- Angular uses environment.ts for configuration
- Store different API keys for dev and production
- Never commit production keys to version control
- Angular CLI automatically uses the correct environment file
// src/environments/environment.ts
export const environment = {
production: false,
issueCaptureApiKey: 'ic_your_api_key_here'
};
// src/environments/environment.prod.ts
export const environment = {
production: true,
issueCaptureApiKey: 'ic_your_production_api_key'
};3
Install via Script Tag (Recommended)
Add IssueCapture to your src/index.html file
- Place script tag at the end of <body> for optimal loading
- type="module" is required for ESM imports
- For dynamic API keys, use programmatic initialization (Step 4)
- Widget loads after Angular app bootstraps
<!-- src/index.html -->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Your Angular App</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
<!-- IssueCapture Widget -->
<script type="module">
import IssueCapture from 'https://issuecapture.com/widget.js';
// Note: Replace with actual API key during build
// Or use programmatic initialization (see Step 4)
IssueCapture.init({
apiKey: 'ic_your_api_key_here', // Replace with your API key
trigger: 'auto',
button: {
position: 'bottom-right',
text: 'Report Bug'
}
});
</script>
</body>
</html>4
Alternative: Programmatic Initialization
Initialize IssueCapture from your AppComponent using ngOnInit
- Loads widget when AppComponent initializes
- Uses environment.ts for API key management
- Cleanup in ngOnDestroy prevents memory leaks
- Useful for SPA with Angular Router
// src/app/app.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { environment } from '../environments/environment';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy {
title = 'your-angular-app';
ngOnInit(): void {
// Dynamically load IssueCapture widget
const script = document.createElement('script');
script.type = 'module';
script.innerHTML = `
import IssueCapture from 'https://issuecapture.com/widget.js';
IssueCapture.init({
apiKey: '${environment.issueCaptureApiKey}',
trigger: 'auto',
button: {
position: 'bottom-right',
text: 'Report Bug'
}
});
`;
document.body.appendChild(script);
}
ngOnDestroy(): void {
// Cleanup on destroy
if ((window as any).IssueCapture) {
(window as any).IssueCapture.destroy();
}
}
}5
Custom Trigger Component
Create an Angular component to trigger the widget
- Use (window as any).IssueCapture.open() to open programmatically
- Check if IssueCapture exists before calling
- Add aria-label for accessibility
- Integrate into navbar, footer, or error handlers
// src/app/components/bug-report-button/bug-report-button.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-bug-report-button',
template: `
<button
(click)="openWidget()"
class="bug-report-btn"
aria-label="Report a bug"
>
Report Bug
</button>
`,
styles: [`
.bug-report-btn {
padding: 0.5rem 1rem;
background: #dd0031;
color: white;
border: none;
border-radius: 0.5rem;
cursor: pointer;
font-weight: 600;
font-size: 1rem;
}
.bug-report-btn:hover {
background: #c3002f;
}
`]
})
export class BugReportButtonComponent {
openWidget(): void {
const issueCapture = (window as any).IssueCapture;
if (issueCapture) {
issueCapture.open();
}
}
}
// Usage in your template:
// <app-bug-report-button></app-bug-report-button>6
Set User Context (Optional)
Pre-fill user information for authenticated users
- Pre-fill reporter name and email for authenticated users
- Update user context when auth state changes
- Component field maps to Jira components for routing
- Improves bug report context for developers
// src/app/app.component.ts
import { Component, OnInit } from '@angular/core';
import { AuthService } from './services/auth.service'; // Your auth service
import { environment } from '../environments/environment';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
constructor(private authService: AuthService) {}
ngOnInit(): void {
// Subscribe to auth state changes
this.authService.user$.subscribe(user => {
if ((window as any).IssueCapture && user) {
this.updateUserContext(user);
}
});
}
private updateUserContext(user: any): void {
(window as any).IssueCapture.init({
apiKey: environment.issueCaptureApiKey,
trigger: 'auto',
user: {
name: user.name,
email: user.email,
component: 'Frontend' // Optional: Jira component
}
});
}
}7
Test the Integration
Verify IssueCapture is working correctly
- Start your dev server: ng serve
- Open your app in the browser
- You should see the floating bug report button
- Click it and submit a test issue
- Check your Jira project for the created issue
- Open browser console and type: window.IssueCapture.isOpen()
Troubleshooting
TypeScript: Property 'IssueCapture' does not exist on type 'Window'
Add type declarations to your project:
// src/types/issuecapture.d.ts
interface IssueCaptureAPI {
init(config: {
apiKey: string
trigger?: string | 'auto'
button?: {
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'
text?: string
icon?: string
}
user?: {
name?: string
email?: string
component?: string
}
}): void
open(): void
close(): void
isOpen(): boolean
destroy(): void
}
declare global {
interface Window {
IssueCapture?: IssueCaptureAPI
}
}
export {}Environment files not being used
- Ensure environment.ts exists in src/environments/
- Check angular.json has correct fileReplacements configuration
- Import from '../environments/environment', not hardcoded paths
- Restart ng serve after changing environment files
Widget loads multiple times (Angular Router)
Initialize widget once in AppComponent, not in child routes:
// src/app/app.component.ts - Initialize once at root level
private isInitialized = false;
ngOnInit(): void {
// Initialize IssueCapture only once
if (!this.isInitialized) {
// Load script...
this.isInitialized = true;
}
}CORS errors when submitting issues
- Add localhost:4200 (Angular default) to allowed domains in dashboard
- Add production domain to allowed domains
- Check IssueCapture dashboard → Widgets → Domains
Advanced Configuration
Event Listeners
(window as any).IssueCapture.init({
apiKey: environment.issueCaptureApiKey,
trigger: 'auto',
onOpen: () => {
console.log('Widget opened')
},
onClose: () => {
console.log('Widget closed')
},
onSubmit: (data: any) => {
console.log('Issue submitted:', data)
// Show success toast, etc.
}
})Error Handler Integration
Create a global error handler to open IssueCapture on errors:
// src/app/error-handler.service.ts
import { ErrorHandler, Injectable } from '@angular/core';
@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
handleError(error: any): void {
console.error('Angular error:', error);
// Open IssueCapture for error reporting
const issueCapture = (window as any).IssueCapture;
if (issueCapture) {
issueCapture.open();
}
}
}
// Register in app.module.ts:
// providers: [
// { provide: ErrorHandler, useClass: GlobalErrorHandler }
// ]Production Best Practices
- Load widget asynchronously to avoid blocking
- Use environment files for API keys
- Whitelist production domains in dashboard
- Test on staging before deploying
Ready to get started?
Sign up for a free account and start collecting bug reports in your Angular app in minutes.