angulardomstripe-paymentsangular-changedetectionng-switch

How to detect ngSwitch changes in Angular page


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>

Solution

  • 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;
        }
     }