---
sidebar_position: 5
---
# 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:

```bash
npm install @myop/react
```

```tsx
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:

```tsx
// 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:

```tsx
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

```bash
npm install @myop/vue
```

```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

```bash
npm install @myop/angular
```

```typescript
// 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

```bash
npm install @myop/sdk
```

```html
<!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`:

```javascript
// 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:

```tsx
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:

```javascript
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:

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

### 5. Type Safety

Define types for better development experience:

```typescript
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

- Review [Best Practices](/docs/learnMyop/html-components/best-practices) for component development
- Learn about [Data Loading](/docs/learnMyop/html-components/data-loading) lifecycle
- Explore the [Public API](/docs/learnMyop/html-components/public-api) reference
