Skip to main content

Host Integration

Learn how to integrate Myop HTML components with your host application using React, Vue, Angular, or vanilla JavaScript.

React Integration​

Using @myop/react​

The @myop/react package provides the MyopContainer component for seamless integration:

npm install @myop/react
import { MyopContainer } from "@myop/react";
import { useNavigate } from "react-router-dom";
import { useEffect, useState } from "react";

export const ComponentList = () => {
const navigate = useNavigate();
const [components, setComponents] = useState([]);

useEffect(() => {
// Fetch data from your API
fetchComponents().then(setComponents);
}, []);

return (
<MyopContainer
componentId="394ee658-b61b-46eb-a0ba-4856e986822d"
onReady={(component) => {
// 1. Set up CTA handler FIRST
component.props.myop_cta_handler = (action, payload) => {
switch (action) {
case 'component_clicked':
navigate(`/component/${payload.componentId}`);
break;
case 'edit':
navigate(`/component/${payload.componentId}/edit`);
break;
case 'delete':
handleDelete(payload.componentId);
break;
}
};

// 2. Initialize with data
component.props.myop_init_interface({ components });
}}
/>
);
};

Data Transformation​

Transform API responses to match your component's expected format:

// Type definitions
interface ApiComponent {
id: string;
name: string;
metadata: {
author: string;
version: string;
lastModified: string;
};
config: {
environments: string[];
tags: string[];
};
}

interface ComponentData {
id: string;
name: string;
developerName: string;
lastEditedDate: string;
lastVersionName: string;
environments: string[];
tags: string[];
}

// Adapter function
function toComponentData(apiComponent: ApiComponent): ComponentData {
return {
id: apiComponent.id,
name: apiComponent.name,
developerName: apiComponent.metadata.author,
lastEditedDate: apiComponent.metadata.lastModified,
lastVersionName: apiComponent.metadata.version,
environments: apiComponent.config.environments,
tags: apiComponent.config.tags
};
}

// Usage
const ComponentList = () => {
return (
<MyopContainer
componentId="..."
onReady={(component) => {
fetchFromApi().then(response => {
const components = response.items.map(toComponentData);
component.props.myop_init_interface({ components });
});
}}
/>
);
};

Updating Component Data​

Update the Myop component when React state changes:

const ComponentList = () => {
const [components, setComponents] = useState([]);
const componentRef = useRef(null);

// Store reference to the Myop component
const handleReady = (component) => {
componentRef.current = component;

component.props.myop_cta_handler = handleAction;

// Initial load
fetchComponents().then(data => {
setComponents(data);
component.props.myop_init_interface({ components: data });
});
};

// Update Myop component when state changes
useEffect(() => {
if (componentRef.current && components.length > 0) {
componentRef.current.props.myop_init_interface({
action: 'setData',
payload: components
});
}
}, [components]);

return <MyopContainer componentId="..." onReady={handleReady} />;
};

Vue Integration​

Using @myop/vue​

npm install @myop/vue
<template>
<MyopContainer
:component-id="componentId"
@ready="onComponentReady"
/>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import { MyopContainer } from '@myop/vue';

const router = useRouter();
const componentId = '394ee658-b61b-46eb-a0ba-4856e986822d';
const myopComponent = ref(null);

const onComponentReady = (component) => {
myopComponent.value = component;

// Set up action handler
component.props.myop_cta_handler = (action, payload) => {
switch (action) {
case 'component_clicked':
router.push(`/component/${payload.componentId}`);
break;
case 'delete':
handleDelete(payload.componentId);
break;
}
};

// Load initial data
loadComponents();
};

const loadComponents = async () => {
const response = await fetch('/api/components');
const data = await response.json();

if (myopComponent.value) {
myopComponent.value.props.myop_init_interface({
components: data.items
});
}
};

onMounted(loadComponents);
</script>

Angular Integration​

Using @myop/angular​

npm install @myop/angular
// component-list.component.ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { MyopContainerComponent } from '@myop/angular';
import { ComponentService } from './component.service';

@Component({
selector: 'app-component-list',
template: `
<myop-container
[componentId]="componentId"
(ready)="onComponentReady($event)">
</myop-container>
`
})
export class ComponentListComponent implements OnInit {
componentId = '394ee658-b61b-46eb-a0ba-4856e986822d';
private myopComponent: any;

constructor(
private router: Router,
private componentService: ComponentService
) {}

ngOnInit() {
this.loadComponents();
}

onComponentReady(component: any) {
this.myopComponent = component;

// Set up action handler
component.props.myop_cta_handler = (action: string, payload: any) => {
switch (action) {
case 'component_clicked':
this.router.navigate(['/component', payload.componentId]);
break;
case 'delete':
this.handleDelete(payload.componentId);
break;
}
};

// Initialize if data already loaded
if (this.components) {
component.props.myop_init_interface({
components: this.components
});
}
}

private components: any[] = [];

private loadComponents() {
this.componentService.getComponents().subscribe(data => {
this.components = data;
if (this.myopComponent) {
this.myopComponent.props.myop_init_interface({
components: data
});
}
});
}

private handleDelete(componentId: string) {
this.componentService.delete(componentId).subscribe(() => {
this.myopComponent.props.myop_init_interface({
action: 'removeItem',
payload: { id: componentId }
});
});
}
}

Vanilla JavaScript Integration​

Using the Host SDK​

npm install @myop/sdk
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
</head>
<body>
<div id="myop-container"></div>

<script type="module">
import { hostSDK } from '@myop/sdk/host';
import { CloudRepository } from '@myop/sdk/helpers';

const componentId = '394ee658-b61b-46eb-a0ba-4856e986822d';
const flowId = '49283058-a787-4fa5-b0d2-516b2e6dc5e3';

async function init() {
// 1. Fetch component configuration
const config = await CloudRepository.Main.fetchComponent(
componentId,
flowId
);

// 2. Load the component
const container = document.getElementById('myop-container');
const component = await hostSDK.loadComponent(config, container);

// 3. Set up action handler
component.props.myop_cta_handler = (action, payload) => {
console.log('Action:', action, payload);

switch (action) {
case 'component_clicked':
window.location.href = `/component/${payload.componentId}`;
break;
}
};

// 4. Fetch and load data
const response = await fetch('/api/components');
const data = await response.json();

component.props.myop_init_interface({
components: data.items
});
}

init();
</script>
</body>
</html>

Integration Best Practices​

1. Set Up Handler Before Data​

Always set up myop_cta_handler before calling myop_init_interface:

// Correct order
component.props.myop_cta_handler = handleAction; // First
component.props.myop_init_interface(data); // Second

// Why: User might interact immediately after data loads

2. Handle Loading States​

Show loading UI while fetching data:

const [isLoading, setIsLoading] = useState(true);

return (
<div>
{isLoading && <LoadingSpinner />}
<MyopContainer
componentId="..."
style={{ display: isLoading ? 'none' : 'block' }}
onReady={(component) => {
fetchData().then(data => {
component.props.myop_init_interface(data);
setIsLoading(false);
});
}}
/>
</div>
);

3. Error Handling​

Handle errors gracefully:

onReady={(component) => {
component.props.myop_cta_handler = handleAction;

fetchData()
.then(data => {
component.props.myop_init_interface(data);
})
.catch(error => {
component.props.myop_init_interface({
error: {
message: error.message,
code: 'FETCH_ERROR'
}
});
});
}}

4. Cleanup on Unmount​

Clean up resources when the host component unmounts:

useEffect(() => {
return () => {
// Clean up if needed
if (componentRef.current) {
componentRef.current = null;
}
};
}, []);

5. Type Safety​

Define types for better development experience:

interface MyopComponent {
props: {
myop_init_interface: (data?: ComponentData | ActionPayload) => void;
myop_cta_handler: (action: ActionType, payload: ActionPayload) => void;
};
}

type ActionType =
| 'component_clicked'
| 'edit'
| 'delete'
| 'refresh';

interface ActionPayload {
componentId?: string;
[key: string]: any;
}

Next Steps​