Angular 8: Stripe elements nested inside Nebular Components
Asked Answered
F

0

0

Problem: I'm running into an issue where I am unable to tokenize the credit card information posted inside of the card stripe element I am mounting to my component.

I am currently using the Nebular stepper component (https://akveo.github.io/nebular/docs/components/stepper/overview#nbsteppercomponent) and have a nested child component with the following ts code:

public async fetchCardInput(): Promise<any> {
    let address: Address = this.ccAddress.fetchAddressData();
    let name = this.getCardholderName();
    let line2 = address.getAddressLine2();

    let cardTokenPayload = {
        name: name,
        address_line1: address.getAddressLine1(),
        address_city: address.getCity(),
        address_state: address.getState(),
        address_zip: address.getZipCode(),
        country: this.constants.US,
        currency: this.constants.USD
    };

    if (line2) {
        cardTokenPayload['address_line2'] = line2;
    }

    const { token, error } = await this.stripe.createToken(this.card, cardTokenPayload);

    if (error) {
        console.log('Something went wrong: ', error);
        return null;
    } else {
        console.log('SUCCESS! Token: ', token);

        let data = {
            tokenId: token.id,
            address: address,
            cardholderName: name
        }

        return data;
    }
}

html (pulled out the html and ts from the child component but it's still behaving the same way):

<nb-step label="Payment / Payout">
  <div class="heading">{{ constants.PAYMENT_INFORMATION }}</div>
  <label class="input-label">{{ constants.CREDIT_CARD_INFORMATION }}</label>
  <div class="card-container">
      <div id="card-element" #cardElement></div>
  </div>
  <div *ngIf="error" class="error mt-10">{{ error }}</div>
</nb-step>

The thing is, this implementation works completely fine when it's not nested inside of the Nebular component. Has anyone found a work-around for this issue or at least familiar with Nebular components and what they're doing under the hood?

EDIT: Adding the browser exception:

ERROR Error: Uncaught (in promise): IntegrationError: We could not retrieve data from the specified Element.
          Please make sure the Element you are attempting to use is still mounted.

I am using Angular 8 and Nebular 4.5.0.

Thanks in advance!

Furnish answered 26/4, 2020 at 21:12 Comment(7)
What exactly is going wrong? Are you getting an error?Chaparro
Yeah, I am getting an exception in the browser. I updated my post with the error.Furnish
are you sure you added stripe script to your file?Glyceric
Hmm, does Nebular stepper remove elements from the DOM when a step is not in view? It looks like the Stripe Element is missing from the DOM which causes stripe.js to fail when you try to use it.Chaparro
@Glyceric Yes, the stripe api calls work just fine when the form is moved outside of the Nebular Stepper component. The issue occurs when the form is nested inside a child <nb-step> component.Furnish
@PaulAsjes that's what I'm guessing. I reached out to their support but haven't gotten an answer yet. I'm guessing the DOM elements are being hidden in the shadow DOM of the <nb-step> component. The weird thing is that when I print out the html element from my typescript file, it knows the element exists before making the call to tokenize the credit card data.Furnish
I got a similar issue when integrated stripe card into the Vue component. My solution for Vue was to move card component initialization from "created" to "mounted" lifecycle hook. I do not see where you do your init, but make sure it happens after the component is fully rendered and div#card-element is visible and won't be manipulated until the card token is fetched.Deckard

© 2022 - 2024 — McMap. All rights reserved.