Angular Examples
Angular integration examples using the Metigan SDK. Learn how to send emails, manage contacts, forms, and audiences in your Angular applications using RxJS Observables.
Installation
terminalTerminal
1
2
3
npm install @metigan/angular
# or
yarn add @metigan/angularModule Configuration
app.module.tsTypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { MetiganModule } from '@metigan/angular';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
HttpClientModule,
// Configure Metigan SDK
MetiganModule.forRoot({
apiKey: 'your-api-key-here',
timeout: 30000,
retryCount: 3
})
],
bootstrap: [AppComponent]
})
export class AppModule { }Basic Component Usage
email.component.tsTypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import { Component, OnInit } from '@angular/core';
import { MetiganService } from '@metigan/angular';
@Component({
selector: 'app-email',
template: `
<div>
<button (click)="sendEmail()" [disabled]="loading">
{{ loading ? 'Sending...' : 'Send Email' }}
</button>
<div *ngIf="message" class="success">{{ message }}</div>
<div *ngIf="error" class="error">{{ error }}</div>
</div>
`
})
export class EmailComponent implements OnInit {
message = '';
error = '';
loading = false;
constructor(private metigan: MetiganService) {}
ngOnInit() {
// Initialize if not done via module
if (!this.metigan.isInitialized()) {
this.metigan.initialize({
apiKey: 'your-api-key-here'
});
}
}
sendEmail() {
this.loading = true;
this.message = '';
this.error = '';
this.metigan.email.sendEmail({
from: 'Your Company <noreply@yourcompany.com>',
recipients: ['customer@email.com'],
subject: 'Welcome!',
content: '<h1>Hello!</h1><p>Thank you for signing up.</p>'
}).subscribe({
next: (response) => {
this.message = `Email sent! ${response.message}`;
this.loading = false;
},
error: (error) => {
this.error = `Error: ${error.message}`;
this.loading = false;
}
});
}
}Using Async Pipe
contacts.component.tsTypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import { Component, OnInit } from '@angular/core';
import { MetiganService } from '@metigan/angular';
import { Observable } from 'rxjs';
@Component({
selector: 'app-contacts',
template: `
<div *ngIf="contacts$ | async as contacts">
<h2>Contacts</h2>
<div *ngFor="let contact of contacts.contacts">
<p>{{ contact.email }} - {{ contact.firstName }} {{ contact.lastName }}</p>
</div>
<p>Total: {{ contacts.pagination.total }}</p>
</div>
`
})
export class ContactsComponent implements OnInit {
contacts$!: Observable<any>;
constructor(private metigan: MetiganService) {}
ngOnInit() {
if (!this.metigan.isInitialized()) {
this.metigan.initialize({ apiKey: 'your-api-key' });
}
this.contacts$ = this.metigan.contacts.list({
audienceId: 'audience-123',
page: 1,
limit: 50
});
}
}Form Submission
form.component.tsTypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MetiganService } from '@metigan/angular';
@Component({
selector: 'app-contact-form',
template: `
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<input formControlName="email" type="email" placeholder="Email" />
<input formControlName="name" placeholder="Name" />
<textarea formControlName="message" placeholder="Message"></textarea>
<button type="submit" [disabled]="form.invalid || loading">
{{ loading ? 'Submitting...' : 'Submit' }}
</button>
<div *ngIf="successMessage">{{ successMessage }}</div>
<div *ngIf="errorMessage" class="error">{{ errorMessage }}</div>
</form>
`
})
export class ContactFormComponent {
form: FormGroup;
loading = false;
successMessage = '';
errorMessage = '';
constructor(
private fb: FormBuilder,
private metigan: MetiganService
) {
this.form = this.fb.group({
email: ['', [Validators.required, Validators.email]],
name: ['', Validators.required],
message: ['', Validators.required]
});
}
onSubmit() {
if (this.form.invalid) return;
this.loading = true;
this.errorMessage = '';
this.successMessage = '';
this.metigan.forms.submit({
formId: 'your-form-id',
data: {
'field-email': this.form.value.email,
'field-name': this.form.value.name,
'field-message': this.form.value.message
}
}).subscribe({
next: (response) => {
this.successMessage = response.message;
this.form.reset();
this.loading = false;
},
error: (error) => {
this.errorMessage = error.message;
this.loading = false;
}
});
}
}Creating Contacts
create-contact.component.tsTypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import { Component, OnDestroy } from '@angular/core';
import { MetiganService } from '@metigan/angular';
import { Subscription } from 'rxjs';
@Component({
selector: 'app-create-contact',
template: `
<form (ngSubmit)="createContact()">
<input [(ngModel)]="email" type="email" placeholder="Email" required />
<input [(ngModel)]="firstName" placeholder="First Name" />
<input [(ngModel)]="lastName" placeholder="Last Name" />
<button type="submit" [disabled]="loading">Create Contact</button>
</form>
`
})
export class CreateContactComponent implements OnDestroy {
email = '';
firstName = '';
lastName = '';
loading = false;
private subscription = new Subscription();
constructor(private metigan: MetiganService) {}
createContact() {
if (!this.email) return;
this.loading = true;
const sub = this.metigan.contacts.create({
email: this.email,
firstName: this.firstName,
lastName: this.lastName,
audienceId: 'audience-123',
tags: ['subscriber']
}).subscribe({
next: (contact) => {
console.log('Contact created:', contact);
this.loading = false;
// Reset form
this.email = '';
this.firstName = '';
this.lastName = '';
},
error: (error) => {
console.error('Error creating contact:', error);
this.loading = false;
}
});
this.subscription.add(sub);
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}Email with Attachments
email-attachment.component.tsTypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import { Component } from '@angular/core';
import { MetiganService } from '@metigan/angular';
@Component({
selector: 'app-email-attachment',
template: `
<div>
<input type="file" #fileInput multiple (change)="onFileSelected($event)" />
<button (click)="sendEmailWithAttachments()" [disabled]="loading || files.length === 0">
Send Email with Attachments
</button>
<div *ngFor="let file of files">{{ file.name }}</div>
</div>
`
})
export class EmailAttachmentComponent {
files: File[] = [];
loading = false;
constructor(private metigan: MetiganService) {}
onFileSelected(event: Event) {
const input = event.target as HTMLInputElement;
if (input.files) {
this.files = Array.from(input.files);
}
}
sendEmailWithAttachments() {
if (this.files.length === 0) return;
this.loading = true;
this.metigan.email.sendEmail({
from: 'sender@example.com',
recipients: ['recipient@example.com'],
subject: 'Email with Attachments',
content: '<p>Please find the attachments below.</p>',
attachments: this.files
}).subscribe({
next: (response) => {
console.log('Email sent with attachments:', response);
this.files = [];
this.loading = false;
},
error: (error) => {
console.error('Error:', error);
this.loading = false;
}
});
}
}Error Handling
error-handling.component.tsTypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import { Component } from '@angular/core';
import { MetiganService, MetiganError, ValidationError, ApiError } from '@metigan/angular';
@Component({
selector: 'app-error-handling',
template: `
<div>
<button (click)="sendEmail()">Send Email</button>
<div *ngIf="error" class="error">{{ error }}</div>
</div>
`
})
export class ErrorHandlingComponent {
error = '';
constructor(private metigan: MetiganService) {}
sendEmail() {
this.error = '';
this.metigan.email.sendEmail({
from: 'invalid-email', // This will cause a validation error
recipients: ['recipient@example.com'],
subject: 'Test',
content: '<p>Test</p>'
}).subscribe({
next: (response) => {
console.log('Success:', response);
},
error: (error) => {
if (error instanceof ValidationError) {
this.error = `Validation Error: ${error.message}`;
} else if (error instanceof ApiError) {
this.error = `API Error (${error.statusCode}): ${error.message}`;
} else if (error instanceof MetiganError) {
this.error = `Metigan Error: ${error.message}`;
} else {
this.error = `Unknown error: ${error.message}`;
}
}
});
}
}Service Injection Pattern
service-example.tsTypeScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import { Injectable } from '@angular/core';
import { MetiganEmailService } from '@metigan/angular';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class EmailService {
constructor(private metiganEmail: MetiganEmailService) {
// Initialize the service
this.metiganEmail.initialize('your-api-key');
}
sendWelcomeEmail(userEmail: string, userName: string): Observable<any> {
return this.metiganEmail.sendEmail({
from: 'noreply@yourapp.com',
recipients: [userEmail],
subject: 'Welcome to Our App!',
content: `<h1>Welcome ${userName}!</h1><p>Thank you for joining us.</p>`
});
}
}
// Use in component
@Component({
selector: 'app-user',
template: ''
})
export class UserComponent {
constructor(private emailService: EmailService) {}
onUserSignup(userEmail: string, userName: string) {
this.emailService.sendWelcomeEmail(userEmail, userName).subscribe({
next: () => console.log('Welcome email sent'),
error: (error) => console.error('Error:', error)
});
}
}RxJS Observables
All Metigan service methods return RxJS Observables. Always subscribe to handle responses and errors. Don't forget to unsubscribe in ngOnDestroyor use the async pipe in templates.
API Key Security
Store your API key in environment variables or a configuration service. Never hardcode API keys in your source code. Use Angular's environment files for different environments.