Skip to content
This repository was archived by the owner on Jan 27, 2024. It is now read-only.

Commit 73ec45a

Browse files
committed
Hoping this fixes #3
Ensure Penpal.connectToChild occurs before iframe is loaded per the docs
1 parent 43b921c commit 73ec45a

File tree

3 files changed

+88
-15
lines changed

3 files changed

+88
-15
lines changed

force-app/main/aura/LC_API/LC_API.cmp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,17 @@ License: BSD 3-Clause License
1414
access="private"
1515
description="Which visualforce page to load for bridging API calls."/>
1616

17-
<aura:attribute name="penpalInitialized"
17+
<aura:attribute name="penpalFrameCreated"
1818
type="Boolean"
1919
access="private"
2020
default="false"
21-
description="Has the Penpal connection been initialized?"/>
21+
description="Has the Penpal iframe been created?"/>
22+
23+
<aura:attribute name="penpalFrameConnected"
24+
type="Boolean"
25+
access="private"
26+
default="false"
27+
description="Has the Penpal iframe been connected?"/>
2228

2329
<aura:handler name="init" value="{!this}" action="{!c.onInit}"/>
2430

@@ -94,8 +100,8 @@ License: BSD 3-Clause License
94100
description="Supports these keys: url (string), options (map)."/>
95101
</aura:method>
96102

97-
<div class="slds-hide">
98-
<iframe aura:id="penpalFrame" src="{!v.iframeSrc}"></iframe>
103+
<div aura:id="penpalFrameContainer" class="slds-hide">
104+
{!v.body}
99105
</div>
100106

101107
</aura:component>

force-app/main/aura/LC_API/LC_APIController.js

Lines changed: 78 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,39 +29,107 @@ License: BSD 3-Clause License
2929
*/
3030
onRender: function( component, event, helper ) {
3131

32-
let initialized = component.get( 'v.penpalInitialized' );
32+
const isPenpalFrameCreated = component.get( 'v.penpalFrameCreated' );
3333

34+
// For Penpal to operate correctly, you must ensure that `connectToChild`
35+
// is called before the iframe has called `connectToParent`.
3436
// Since the iframe source is calculated asynchronously,
3537
// we listen to the component's render events and each time
36-
// check if the iframe is ready, and if so, then we initialize
38+
// check if the iframe source is ready, and if so, then we initialize
3739
// penpal to connect this component to the iframe.
3840
// Since we only want to do this once, we also set the initialized flag.
39-
if ( !initialized ) {
41+
if ( !isPenpalFrameCreated ) {
4042

41-
let iframeElmt = component.find( 'penpalFrame' ).getElement();
43+
const container = component.find( 'penpalFrameContainer' );
44+
const iframeSrc = component.get( 'v.iframeSrc' );
4245

43-
if ( !$A.util.isEmpty( iframeElmt.src ) ) {
46+
// Ensure the container element has rendered otherwise we can't
47+
// append child elements to it. And wait for the iframe source to
48+
// be available otherwise no reason to create the iframe element.
49+
if ( !$A.util.isEmpty( container ) && !$A.util.isEmpty( iframeSrc ) ) {
4450

45-
component.set( 'v.penpalInitialized', true );
51+
$A.createComponent(
52+
"aura:html",
53+
{
54+
"aura:id": "penpalFrame",
55+
"tag": "iframe",
56+
"HTMLAttributes": {
57+
"src": iframeSrc
58+
}
59+
},
60+
function ( iframeCmp, status, errorMessage ) {
61+
62+
// This callback happened asynchronously, so make one
63+
// more check on whether the penpal frame has been initialized or not
64+
// in the off chance a separate render cycle got here before this one.
65+
const isPenpalFrameCreated = component.get( 'v.penpalFrameCreated' );
66+
67+
if ( isPenpalFrameCreated ) {
68+
69+
console.log( 'LC_API: iframe is already initialized' );
70+
71+
} else if ( status === 'SUCCESS' ) {
72+
73+
// At this point, the iframe component has been constructed
74+
// but not yet been rendered, so we don't have access to the
75+
// HTML iframe element yet. We need to wait for another render cycle,
76+
// that is, we need to wait for the render() method to be called again
77+
// after we append the new iframe component to the body of its container.
78+
// Once we're able to find the 'penpalFrame' on the page then
79+
// we can proceed with the rest of the penpal initialization.
80+
81+
component.set( 'v.penpalFrameCreated', true );
82+
83+
container.set( 'v.body', [ iframeCmp ] );
84+
85+
console.info( 'LC_API: iframe initialized' );
86+
87+
} else if ( status === 'INCOMPLETE' ) {
88+
89+
console.warn( 'LC_API: No response from server or client is offline' );
90+
91+
} else if ( status === 'ERROR' ) {
92+
93+
console.error( 'LC_API: Error creating iframe: ' + errorMessage );
94+
95+
}
96+
97+
}
98+
);
99+
100+
} // else, iframe source is empty, keep waiting
101+
102+
} else {
103+
104+
const isPenpalFrameConnected = component.get( 'v.penpalFrameConnected' );
105+
const iframeCmp = component.find( 'penpalFrame' );
106+
107+
if ( !$A.util.isEmpty( iframeCmp ) && !isPenpalFrameConnected ) {
46108

47109
const connection = Penpal.connectToChild({
48110
// The iframe to which a connection should be made
49-
iframe: iframeElmt
111+
iframe: iframeCmp.getElement()
50112
});
51113

52114
helper._penpal.connection = connection;
53115

54116
connection.promise.then( $A.getCallback( function( child ) {
117+
55118
// Cache a reference to the child so that we can
56119
// use it in the restRequest/fetchRequest methods,
57120
// as well as be able to destroy it when this component unrenders.
58121
helper._penpal.child = child;
122+
console.info( 'LC_API: connected to iframe ' + iframeCmp.getGlobalId() );
123+
component.set( 'v.penpalFrameConnected', true );
124+
59125
})).catch( $A.getCallback( function( err ) {
60-
console.error( 'LC_API: Error establishing connection to iframe', err );
61-
component.set( 'v.penpalInitialized', false );
126+
127+
console.error( 'LC_API: Error establishing connection to iframe ' + iframeCmp.getGlobalId(), err );
128+
component.set( 'v.penpalFrameConnected', false );
129+
62130
}));
63131

64-
} // else, iframe source is empty, keep waiting
132+
}
65133

66134
}
67135

force-demo/main/tabs/LC_Demo.tab-meta.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,5 @@
33
<description>Created by Lightning App Builder</description>
44
<flexiPage>LC_Demo</flexiPage>
55
<label>LC Demo</label>
6-
<mobileReady>true</mobileReady>
76
<motif>Custom9: Lightning</motif>
87
</CustomTab>

0 commit comments

Comments
 (0)