Currently I am integrating Stripe into Angular. The implementation works fine until I started moving the Stripe Elements into an ngSwitchCase
and ng-container
That's when I started getting this error:
ERROR IntegrationError: The selector you specified (#card-element) applies to no DOM elements
that are currently on the page.
Make sure the element exists on the page before calling mount()
The reason is that stripe tries to mount
the element before the ngSwitchCase
shows up. I tried using ngAfterViewInit
but it seems that the function is executed once when the component is rendered for the first time and not when ngSwitch
changes the view.
Is there a way I can detect changes in the view of the component? That way I know when to mount()
the Stripe elements after the component is completely rendered. Note below that I am using ng-container
which do not adds DOM nodes to the HTML, according to the Angular docs.
<ng-container [ngSwitch]="selectedForm">
<ng-container *ngSwitchCase="'FORM_ONE'">
<form>
...
</form>
</ng-container>
<ng-container *ngSwitchCase="'FORM_TWO'">
<form>
...
</form>
</ng-container>
<ng-container *ngSwitchCase="'FORM_THREE'">
// Stripe 'card-element'
<form action="/charge" method="post" id="payment-form">
<label for="card-element">Credit or debit card</label>
<div id="card-element"></div>
<div id="card-errors" role="alert"></div>
</form>
</ng-container>
</ng-container>
in the template add a name to the card
<ng-container *ngSwitchCase="'FORM_THREE'">
// Stripe 'card-element'
<form action="/charge" method="post" id="payment-form">
<label for="card-element">Credit or debit card</label>
<div #stripeCard id="card-element"></div>
<div id="card-errors" role="alert"></div>
</form>
</ng-container>
now, you can be notified when rendered by using a setter. in component:
card:ElementRef;
@ViewChild('stripeCard') set content(content: ElementRef) {
if(content) { // initially setter gets called with undefined
//mount it here...
//for future reference...
this.card=content;
}
}