Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CardElement cannot be attached to elements inside Angular Material tabs #870

Open
phx-evan-hilscher opened this issue Feb 6, 2024 · 0 comments

Comments

@phx-evan-hilscher
Copy link

I'm using @types/recurly__recurly-js to include Recurly elements in my Angular app. When I try to attach a CardElement to an element inside a non-default Angular Material tab, I get this error when switching to the tab (Chrome):

core.mjs:11860 ERROR TypeError: Cannot read properties of null (reading 'postMessage')
    at recurly.js:2:6789
    at Array.forEach (<anonymous>)
    at s.value (recurly.js:2:6766)
    at i.value (recurly.js:2:15668)
    at i.value (recurly.js:2:16227)
    at i.<anonymous> (recurly.js:2:11234)
    at e.emit (recurly.js:2:146300)
    at recurly.js:2:6885
    at Array.forEach (<anonymous>)
    at s.value (recurly.js:2:6766)

My very simple markup:

<mat-tab-group>
  <mat-tab label="Default">
    <h3>Default</h3>
  </mat-tab>
  <mat-tab label="Subscription">
    <div>
      <h3>Subscription</h3>
    
      <input type="text" data-recurly="first_name">
      <input type="text" data-recurly="last_name">
    
      <div #recurlyElements>
        <!-- Recurly Elements will be attached here -->
      </div>
    
      <!-- Recurly.js will update this field automatically -->
      <input type="hidden" name="recurly-token" data-recurly="token">
    
      <button>submit</button>
    </div>
  </mat-tab>
</mat-tab-group>

and component definition:

import { CommonModule } from '@angular/common';
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { RecurlyOptions } from '@recurly/recurly-js'
import { MatTabsModule } from '@angular/material/tabs'

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, MatTabsModule, RouterOutlet],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})
export class AppComponent implements OnInit, AfterViewInit {
  title = 'recurly_test';

  @ViewChild('recurlyElements')
  recurlyElements? : ElementRef;

  ngOnInit() {
    recurly.configure({publicKey: 'REDACTED'} as RecurlyOptions);
  }

  ngAfterViewInit(): void {
    const elements = recurly.Elements();
    const cardElement = elements.CardElement();
    cardElement.attach(this.recurlyElements?.nativeElement);
  }
}

I've traced the issue to line 261 here:

/**
* Attach the element to an HTMLElement
*
* Usage
*
* ```
* element.attach('#my-card-container');
* ```
*
* ```
* element.attach(document.querySelector('#my-card-container'));
* ```
*
* @public
* @param {HTMLElement|String} parent element or selector reference to the attach target
*/
attach (parent) {
parent = dom.element(parent);
if (!parent) {
throw new Error('Invalid parent. Expected HTMLElement.');
}
const { attached, bus, container, id } = this;
debug('attach', id);
if (attached) {
if (container.parentElement === parent) return this;
this.remove();
}
parent.appendChild(container);
bus.add(this.window);
this.once(this.messageName('ready'), () => this.emit('attach', this));
return this;
}

this.window is null. window() is an alias for this.iframe.contentWindow, which is expected to be non-null after appendChild (line 260), as this.iframe is nested inside container. If the CardElement is not inside an Angular Material tab, or the default tab is the tab containing this CardElement, then there is no problem.

I do not have a good solution. Perhaps bus.add should be inside the 'ready' handler (line 262), but I do not know enough about this framework to tell if that will work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant