Home > Documentation > Examples > Basic Parent-Child Communication
Basic Parent-Child Communication Example
A complete working example showing ParleyJS communication between a parent window and an iframe.
Table of Contents
- Overview
- Prerequisites
- Project Structure
- Parent Window Implementation
- Child Window Implementation
- Understanding the Code
- Running the Example
- Common Issues
- Next Steps
Overview
This example demonstrates the fundamental pattern for ParleyJS communication between a parent window and an iframe. The parent sends a request to the child, and the child responds with data.
What you will learn:
- Creating a ParleyJS instance with origin validation
- Connecting to an iframe
- Sending messages and receiving responses
- Handling errors and timeouts
- Using TypeScript for type safety
Prerequisites
Before starting, ensure you have:
- ParleyJS installed in your project
- Basic understanding of iframes and the postMessage API
- A local development server (for HTTPS in production)
For installation instructions, see Installation Guide.
Project Structure
Create the following files in your project:
project/
├── parent.html # Parent window
├── child.html # Child iframe
├── parent.ts # Parent logic
└── child.ts # Child logicParent Window Implementation
parent.html
<!DOCTYPE html>
<html>
<head>
<title>ParleyJS Parent Example</title>
</head>
<body>
<h1>Parent Window</h1>
<button id="send-message">Send Message to Child</button>
<div id="response"></div>
<iframe
id="child-frame"
src="child.html"
width="600"
height="400"
></iframe>
<script type="module" src="parent.ts"></script>
</body>
</html>parent.ts
import { Parley, SYSTEM_EVENTS } from 'parley-js';
import type { TimeoutError, ValidationError } from 'parley-js';
// Define message types for type safety
interface DataRequest {
userId: number;
}
interface DataResponse {
success: boolean;
user: {
id: number;
name: string;
email: string;
};
}
// Create ParleyJS instance with origin validation
const parley = Parley.create({
allowedOrigins: [window.location.origin],
timeout: 5000,
debug: true,
});
// Get DOM elements
const iframe = document.getElementById('child-frame') as HTMLIFrameElement;
const sendButton = document.getElementById('send-message') as HTMLButtonElement;
const responseDiv = document.getElementById('response') as HTMLDivElement;
// Wait for iframe to load before connecting
iframe.addEventListener('load', async () => {
try {
// Connect to the iframe
await parley.connect(iframe.contentWindow!, 'child-iframe');
console.log('Connected to child iframe');
// Enable the send button
sendButton.disabled = false;
} catch (error) {
console.error('Failed to connect to iframe:', error);
responseDiv.textContent = 'Connection failed';
}
});
// Listen for connection events
parley.onSystem(SYSTEM_EVENTS.CONNECTED, (event) => {
console.log('Child connected:', event.targetId);
responseDiv.textContent = 'Ready to send messages';
});
parley.onSystem(SYSTEM_EVENTS.DISCONNECTED, (event) => {
console.log('Child disconnected:', event.targetId, event.reason);
responseDiv.textContent = 'Child disconnected';
sendButton.disabled = true;
});
// Handle send button click
sendButton.addEventListener('click', async () => {
try {
// Show loading state
responseDiv.textContent = 'Sending request...';
sendButton.disabled = true;
// Send request to child and wait for response
const response = await parley.send<DataRequest, DataResponse>(
'get-user-data',
{ userId: 123 },
{
targetId: 'child-iframe',
timeout: 5000,
}
);
// Handle successful response
if (response.success) {
responseDiv.innerHTML = `
<h3>User Data Received:</h3>
<p>ID: ${response.user.id}</p>
<p>Name: ${response.user.name}</p>
<p>Email: ${response.user.email}</p>
`;
} else {
responseDiv.textContent = 'Failed to retrieve user data';
}
} catch (error) {
// Handle different error types
if (error instanceof TimeoutError) {
responseDiv.textContent =
'Request timed out. Child may be unresponsive.';
console.error('Timeout error:', error);
} else if (error instanceof ValidationError) {
responseDiv.textContent = 'Invalid response from child.';
console.error('Validation error:', error);
} else {
responseDiv.textContent =
'Request failed. See console for details.';
console.error('Request error:', error);
}
} finally {
// Re-enable button
sendButton.disabled = false;
}
});
// Clean up when page unloads
window.addEventListener('beforeunload', () => {
parley.disconnect('child-iframe');
});Child Window Implementation
child.html
<!DOCTYPE html>
<html>
<head>
<title>ParleyJS Child Example</title>
</head>
<body>
<h1>Child Iframe</h1>
<p>Waiting for requests from parent...</p>
<div id="status">Not connected</div>
<script type="module" src="child.ts"></script>
</body>
</html>child.ts
import { Parley, SYSTEM_EVENTS } from 'parley-js';
import type { MessageMetadata, ResponseFunction } from 'parley-js';
// Define message types
interface DataRequest {
userId: number;
}
interface DataResponse {
success: boolean;
user: {
id: number;
name: string;
email: string;
};
}
// Create ParleyJS instance
const parley = Parley.create({
allowedOrigins: [window.location.origin],
debug: true,
});
const statusDiv = document.getElementById('status') as HTMLDivElement;
// Register message handler for 'get-user-data' requests
parley.on<DataRequest>(
'get-user-data',
async (
payload,
respond: ResponseFunction<DataResponse>,
metadata: MessageMetadata
) => {
console.log('Received request from parent:', payload);
statusDiv.textContent = `Processing request for user ${payload.userId}...`;
try {
// Simulate data fetch (in real app, this would be an API call)
const userData = await fetchUserData(payload.userId);
// Send success response
respond({
success: true,
user: userData,
});
statusDiv.textContent = `Sent user data for ID ${payload.userId}`;
} catch (error) {
// Send error response
respond({
success: false,
user: null as any,
});
statusDiv.textContent = `Failed to fetch user ${payload.userId}`;
console.error('Error fetching user data:', error);
}
}
);
// Simulate fetching user data
async function fetchUserData(userId: number) {
// Simulate network delay
await new Promise((resolve) => setTimeout(resolve, 500));
// Return mock data
return {
id: userId,
name: 'Alice Johnson',
email: 'alice@example.com',
};
}
// Connect to parent window
(async () => {
try {
await parley.connect(window.parent, 'parent-window');
console.log('Connected to parent');
} catch (error) {
console.error('Failed to connect to parent:', error);
statusDiv.textContent = 'Connection failed';
}
})();
// Listen for connection events
parley.onSystem(SYSTEM_EVENTS.CONNECTED, (event) => {
console.log('Connected to parent:', event.targetId);
statusDiv.textContent = 'Connected to parent - Ready';
});
parley.onSystem(SYSTEM_EVENTS.MESSAGE_RECEIVED, (event) => {
console.log('Message received:', event.messageType);
});Understanding the Code
Origin Validation
Both parent and child use strict origin validation:
allowedOrigins: [window.location.origin];This ensures only messages from the same origin are accepted. In production, specify the exact origins you trust.
For more on origin validation, see Origin Validation Guide.
Connection Establishment
The parent waits for the iframe to load before connecting:
iframe.addEventListener('load', async () => {
await parley.connect(iframe.contentWindow!, 'child-iframe');
});The child connects to the parent immediately:
await parley.connect(window.parent, 'parent-window');For connection patterns, see iFrame Communication Guide.
Type Safety
TypeScript generics provide type safety for messages:
await parley.send<DataRequest, DataResponse>(
'get-user-data',
{ userId: 123 },
{ targetId: 'child-iframe' }
);The compiler ensures request and response types match your interfaces.
Error Handling
The example handles three error types:
- TimeoutError: Request took too long
- ValidationError: Response failed schema validation
- Generic errors: Other communication failures
For comprehensive error handling patterns, see Error Handling Pattern.
System Events
System events provide visibility into the communication lifecycle:
parley.onSystem(SYSTEM_EVENTS.CONNECTED, (event) => {
console.log('Connected:', event.targetId);
});For all available system events, see System Events Reference.
Running the Example
Development Server
Start a local development server:
# Using Python
python -m http.server 8000
# Using Node.js (http-server)
npx http-server -p 8000
# Using VS Code Live Server
# Install Live Server extension and click "Go Live"Open in Browser
Navigate to http://localhost:8000/parent.html
Expected Behavior
- Parent page loads with iframe
- Connection establishes automatically
- Click "Send Message to Child"
- User data appears in response div
- Console shows all communication events
Common Issues
Issue: Connection Timeout
Symptom: "Failed to connect to iframe" error
Solution: Ensure the iframe has fully loaded before connecting. Use the load event listener as shown in the example.
For more timeout troubleshooting, see Timeout Errors.
Issue: Origin Mismatch
Symptom: Messages not received, console shows origin errors
Solution: Verify allowedOrigins matches the actual origin. Use window.location.origin for same-origin communication.
For origin troubleshooting, see Origin Mismatch Errors.
Issue: TypeScript Errors
Symptom: Type errors when using send() or on()
Solution: Define proper interfaces for request and response types. See TypeScript examples in this guide.
Next Steps
Now that you understand the basics:
Add Schema Validation - Validate message payloads with JSON Schema
Implement Error Recovery - Add retry logic and fallback handling
Monitor Connection Health - Use heartbeat monitoring
Scale to Multiple Windows - Communicate with multiple iframes
Learn Advanced Patterns - Request-response, state sync, broadcasting
- See Code Patterns
Related Documentation
API Reference:
- Parley.create() - Instance creation
- connect() - Establish connections
- send() - Send messages
- on() - Register handlers
Guides:
- First Example - Step-by-step tutorial
- iFrame Communication - Complete iframe guide
- Security Best Practices - Secure communication
Patterns:
- Request-Response Pattern - Messaging patterns
- Error Handling Pattern - Error strategies
Previous: Examples Overview Next: Advanced Examples Back to: Examples
