Updated Version
A newer version of this article can be found here:
Scenario
During checkout we want to obtain a checkout token from Stripe using Stripe Elements and Angular.
Approach
Stackblitz
Go to stackblitz and start a brand new Angular project. Delete the hello.component.ts
and remove it from app.module.ts
correspondingly. Remove the <hello name=”{{ name }}”></hello>
from app.component.html
.
Dependencies
Add this dependency to your Stackblitz dependencies.
Initialize Stripe Elements
Constructor inject the AngularStripeService
into app.component.ts
import { AngularStripeService } from '@fireflysemantics/angular-stripe-service';constructor(
private cd: ChangeDetectorRef,
private stripeService:AngularStripeService) {}
Initialize stripe elements:
ngAfterViewInit() {this.stripeService.setPublishableKey('pk_test_2syov9fTMRwOxYG97AAXbOgt008X6NL46o').then(stripe=> { this.stripe = stripe; const elements = stripe.elements(); this.card = elements.create('card'); this.card.mount(this.cardInfo.nativeElement); this.card.addEventListener('change', this.cardHandler);
});
}
Note that key pk_test_2syov9fTMRwOxYG97AAXbOgt008X6NL46o
is a temporary key used for this demo. You will need to provide your own.
Import the Form Module
In app.module.ts
:
import {FormsModule} from '@angular/forms';
Markup
Put the following markup in app.component.html
:
<form #checkout="ngForm" (ngSubmit)="onSubmit(checkout)" class="checkout">
<div class="form-row">
<label for="card-info">Card Info</label>
<div id="card-info" #cardInfo></div>
<div id="card-errors" role="alert" *ngIf="error">{{ error }}</div></div>
<button type="submit">Pay $5</button>
</form>
CSS
Add the CSS to app.component.css
:
form.checkout {
max-width: 500px;
margin: 2rem auto;
text-align: center;
border: 2px solid #eee;
border-radius: 8px;
padding: 1rem 2rem;
background: white;
font-family: monospace;
color: #525252;
font-size: 1.1rem;
}form.checkout button {
padding: 0.5rem 1rem;
color: white;
background: coral;
border: none;
border-radius: 4px;
margin-top: 1rem;
}form.checkout button:active {
background: rgb(165, 76, 43);
}
Demo
Analysis
The @fireflysemantics/angular-stripe-service
service injects the Stripe scripts for us and waits for it to load before attempting to initialize elements
.
The reason this is important is that if our component containing the Stripe form is loaded before Stripe has a chance to initialize elements
then the form will not paint correctly.
In other words the Stripe API download and subsequent elements
construction is racing the construction of the credit card form component.
If the form component wins that race, the component does not get constructed right, because elements
is not yet available.