Card Elements
You can mount individual Element components inside of your
One Element
In this example the
import { Component, inject, ViewChild } from '@angular/core';
import { UntypedFormBuilder, Validators } from '@angular/forms';
import { MatInputModule } from '@angular/material/input';
import {
injectStripe,
StripeElementsDirective
StripeCardComponent
} from 'ngx-stripe';
import {
StripeElementsOptions,
StripeCardElementOptions
} from '@stripe/stripe-js';
@Component({
selector: 'ngstre-one-element-card',
template: `
<h2>Card Example</h2>
<div [formGroup]="checkoutForm">
<mat-form-field class="example-full-width" appearance="fill">
<input matInput placeholder="name" formControlName="name" />
</mat-form-field>
<mat-form-field class="example-full-width" appearance="fill">
<input matInput placeholder="Email" type="email" formControlName="email" />
</mat-form-field>
<ngx-stripe-elements
[stripe]="stripe"
[elementsOptions]="elementsOptions"
>
<ngx-stripe-card [options]="cardOptions" />
</ngx-stripe-elements>
</div>
<button type="submit" (click)="createToken()">
CREATE TOKEN
</button>
`,
standalone: true,
imports: [
ReactiveFormsModule,
MatInputModule,
StripeElementsDirective,
StripeCardComponent
]
})
export class CreateTokenComponent {
@ViewChild(StripeCardComponent) cardElement!: StripeCardComponent;
private readonly fb = inject(UntypedFormBuilder);
cardOptions: StripeCardElementOptions = {
style: {
base: {
iconColor: '#666EE8',
color: '#31325F',
fontWeight: '300',
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSize: '18px',
'::placeholder': {
color: '#CFD7E0'
}
}
}
};
elementsOptions: StripeElementsOptions = {
locale: 'en'
};
checkoutForm = this.fb.group({
name: ['', [Validators.required]],
email: ['', [Validators.required, Validators.email]]
});
// Replace with your own public key
stripe = injectStripe(this.yourOwnAPI.StripePublicKey);
createToken() {
const name = this.stripeTest.get('name').value;
this.stripe
.createToken(this.card.element, { name })
.subscribe((result) => {
if (result.token) {
// Use the token
console.log(result.token.id);
} else if (result.error) {
// Error creating the token
console.log(result.error.message);
}
});
}
}
Card Group
If you want to use the card number, expiry and cvc as separated elements you need to put them inside the card group directive.
This is necessary to ensure the three elements share the same stripe elements objects, otherwise it won't work. As you can see in the example, element options is not available for any of the three child components, but only for the group directive.
Here is an example using the Card Group as a Directive:
import { Component, OnInit, ViewChild, ɵConsole } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { StripeService, StripeCardNumberComponent } from 'ngx-stripe';
import {
StripeCardElementOptions,
StripeElementsOptions,
PaymentIntent,
} from '@stripe/stripe-js';
import { environment as env } from '../../environments/environment';
@Component({
selector: 'app-simple-payment-intent',
templateUrl: './simple-payment-intent.component.html',
styleUrls: ['./simple-payment-intent.component.css'],
})
export class SimplePaymentIntentComponent implements OnInit {
@ViewChild(StripeCardNumberComponent) card: StripeCardNumberComponent;
cardOptions: StripeCardElementOptions = {
style: {
base: {
iconColor: '#666EE8',
color: '#31325F',
fontWeight: '300',
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSize: '18px',
'::placeholder': {
color: '#CFD7E0',
},
},
},
};
elementsOptions: StripeElementsOptions = {
locale: 'es',
};
stripeTest: FormGroup;
constructor(
private http: HttpClient,
private fb: FormBuilder,
private stripeService: StripeService
) {}
ngOnInit(): void {
this.stripeTest = this.fb.group({
name: ['Angular v10', [Validators.required]],
amount: [1001, [Validators.required, Validators.pattern(/d+/)]],
});
}
pay(): void {
if (this.stripeTest.valid) {
this.createPaymentIntent(this.stripeTest.get('amount').value)
.pipe(
switchMap((pi) =>
this.stripeService.confirmCardPayment(pi.client_secret, {
payment_method: {
card: this.card.element,
billing_details: {
name: this.stripeTest.get('name').value,
},
},
})
)
)
.subscribe((result) => {
if (result.error) {
// Show error to your customer (e.g., insufficient funds)
console.log(result.error.message);
} else {
// The payment has been processed!
if (result.paymentIntent.status === 'succeeded') {
// Show a success message to your customer
}
}
});
} else {
console.log(this.stripeTest);
}
}
createPaymentIntent(amount: number): Observable<PaymentIntent> {
return this.http.post<PaymentIntent>(
`${env.apiUrl}/create-payment-intent`,
{ amount }
);
}
}
We also make available the component selector, in case you prefer to work that way, here is an example using the Card Group as a Component.
import { Component, OnInit, ViewChild, ɵConsole } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { StripeService, StripeCardNumberComponent } from 'ngx-stripe';
import {
StripeCardElementOptions,
StripeElementsOptions,
PaymentIntent,
} from '@stripe/stripe-js';
import { environment as env } from '../../environments/environment';
@Component({
selector: 'app-simple-payment-intent',
templateUrl: './simple-payment-intent.component.html',
styleUrls: ['./simple-payment-intent.component.css'],
})
export class SimplePaymentIntentComponent implements OnInit {
@ViewChild(StripeCardNumberComponent) card: StripeCardNumberComponent;
cardOptions: StripeCardElementOptions = {
style: {
base: {
iconColor: '#666EE8',
color: '#31325F',
fontWeight: '300',
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSize: '18px',
'::placeholder': {
color: '#CFD7E0',
},
},
},
};
elementsOptions: StripeElementsOptions = {
locale: 'es',
};
stripeTest: FormGroup;
constructor(
private http: HttpClient,
private fb: FormBuilder,
private stripeService: StripeService
) {}
ngOnInit(): void {
this.stripeTest = this.fb.group({
name: ['Angular v10', [Validators.required]],
amount: [1001, [Validators.required, Validators.pattern(/d+/)]],
});
}
pay(): void {
if (this.stripeTest.valid) {
this.createPaymentIntent(this.stripeTest.get('amount').value)
.pipe(
switchMap((pi) =>
this.stripeService.confirmCardPayment(pi.client_secret, {
payment_method: {
card: this.card.element,
billing_details: {
name: this.stripeTest.get('name').value,
},
},
})
)
)
.subscribe((result) => {
if (result.error) {
// Show error to your customer (e.g., insufficient funds)
console.log(result.error.message);
} else {
// The payment has been processed!
if (result.paymentIntent.status === 'succeeded') {
// Show a success message to your customer
}
}
});
} else {
console.log(this.stripeTest);
}
}
createPaymentIntent(amount: number): Observable<PaymentIntent> {
return this.http.post<PaymentIntent>(
`${env.apiUrl}/create-payment-intent`,
{ amount }
);
}
}