@myop/angular
Official Angular bindings for embedding Myop components in your Angular applications.
Myop components are framework-agnostic UI components that can be updated in real-time without redeploying your application. Build once, embed anywhere, and iterate instantly. Perfect for teams that need to ship UI changes fast, A/B test components, or empower non-developers to customize the interface. Myop is also the safest way to adopt AI-generated components in your application—whether created by developers or non-developers—with built-in sandboxing and controlled integration.
Website | Documentation | Dashboard | Discord
Installation
npm install @myop/angular
yarn add @myop/angular
pnpm add @myop/angular
Auto-Generated Angular Components
Myop automatically generates a typed Angular component package for every component you create in the dashboard. Install it directly via npm:
npm install https://cloud.myop.dev/npm/{component-id}/angular
Setup (One-Time Configuration)
Add node_modules/@myop to your TypeScript compilation in tsconfig.app.json:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app"
},
"include": [
"src/**/*.d.ts",
"src/**/*.ts",
"node_modules/@myop/**/*.ts"
]
}
This allows Angular to compile the auto-generated component packages alongside your application code.
Usage
Import and use the generated component directly. For example, if you created a table component called "users-table" in the dashboard:
import { Component } from "@angular/core";
import { UsersTableComponent, UsersTableCtaPayloads, CtaEvent } from "@myop/users-table";
@Component({
selector: "app-root",
standalone: true,
imports: [UsersTableComponent],
template: `
<users-table
[data]="{ rows: users }"
(cta)="onCta($event)"
/>
`,
})
export class AppComponent {
users = [
{ id: 1, name: "Alice", email: "alice@example.com", role: "Admin" },
{ id: 2, name: "Bob", email: "bob@example.com", role: "User" },
{ id: 3, name: "Charlie", email: "charlie@example.com", role: "User" },
];
onCta(event: CtaEvent<UsersTableCtaPayloads>) {
switch (event.action) {
case "rowClicked":
console.log("Selected user:", event.payload.rowData);
break;
case "deleteClicked":
this.deleteUser(event.payload.userId);
break;
case "exportRequested":
this.exportToFormat(event.payload.format);
break;
}
}
}
Why this is powerful:
- Fully typed — The generated package includes complete TypeScript types for your component's data interface and all CTA event payloads
- Auto loaded — Components are fetched and rendered automatically, no manual setup required
- Not in your code — The actual component implementation lives on Myop and is loaded at runtime. Update your component in the dashboard and it's instantly live—no rebuild, no redeploy
- Zero bundle impact — The entire
@myop/angularpackage costs only ~6KB gzipped—and that's the total cost whether you use 1, 2, or 1,000 components. Auto-generated component packages are just thin typed wrappers. The actual component implementations are loaded at runtime, meaning your Myop components can be as complex, feature-rich, and heavy as you need without adding a single byte to your application bundle. Consider typical bundle costs: a chart library (~60KB), a map component (~200KB), a data grid (~150KB), a rich text editor (~100KB), or a chat widget with emoji picker (~80KB). With Myop, all of these cost ~0KB to your bundle—they load on-demand when needed
Environment options:
Set the default environment for all components using setEnvironment:
import { setEnvironment } from "@myop/angular";
// Set default environment for all component loads
setEnvironment("staging");
You can also override the environment directly on a specific component:
<myop-users-table
[data]="{ rows: users }"
[preview]="true"
environment="staging"
/>
Environments are fully configurable in the dashboard, allowing you to test changes in staging before publishing to production.
For more details on auto-generated packages, see the Auto-Generated Packages documentation.
Requirements
- Angular 17.0+
Quick Start
import { Component } from "@angular/core";
import { MyopComponent } from "@myop/angular";
@Component({
selector: "app-root",
standalone: true,
imports: [MyopComponent],
template: `
<myop-component
[componentId]="'your-component-id'"
[style]="{ width: '600px', height: '400px' }"
(action)="onAction($event)"
/>
`,
})
export class AppComponent {
onAction(event: { action: string; payload: any }) {
console.log("Action:", event.action, "Payload:", event.payload);
}
}
Components
myop-component
The main component for embedding Myop components.
import { Component } from "@angular/core";
import { MyopComponent } from "@myop/angular";
@Component({
selector: "app-dashboard",
standalone: true,
imports: [MyopComponent],
template: `
<myop-component
[componentId]="'abc123'"
[data]="{ items: items }"
(rowClicked)="onRowClicked($event)"
(load)="onLoad($event)"
(error)="onError($event)"
/>
`,
})
export class DashboardComponent {
items = [
{ id: 1, name: "Item 1" },
{ id: 2, name: "Item 2" },
];
onRowClicked(payload: any) {
console.log("Row clicked:", payload);
}
onLoad(component: any) {
console.log("Loaded!", component);
}
onError(error: string) {
console.error("Error:", error);
}
}
Inputs
| Input | Type | Description |
|---|---|---|
componentId | string | The ID of the Myop component to load |
data | object | Data to pass to the component via myop_init_interface |
style | object | CSS styles for the container |
fadeDuration | number | Loader fade-out duration in ms (default: 200) |
environment | string | Load from a specific environment (e.g., "staging", "prod") |
preview | boolean | Load the unpublished preview version of the component |
Outputs
| Output | Type | Description |
|---|---|---|
(action) | EventEmitter<{action, payload}> | Generic handler for all CTA events |
([actionName]) | EventEmitter<payload> | Handler for specific actions (e.g., (rowClicked)) |
(load) | EventEmitter<component> | Called when the component finishes loading |
(error) | EventEmitter<string> | Called when loading fails |
Inputs for Loading/Fallback
| Input | Type | Description |
|---|---|---|
loader | TemplateRef | Loading indicator template (default: null - no loader). Use MyopLoader for default Myop loader |
fallback | TemplateRef | Error fallback template (default: built-in MyopFallback). Override with custom template |
Environments & Preview
Myop supports multiple environments, allowing you to test changes before going live:
<!-- Production (default) -->
<myop-component [componentId]="'abc123'" />
<!-- Load from staging environment -->
<myop-component [componentId]="'abc123'" environment="staging" />
<!-- Load unpublished preview version (for testing before publishing) -->
<myop-component [componentId]="'abc123'" [preview]="true" />
<!-- Combine both: preview version in staging -->
<myop-component [componentId]="'abc123'" environment="staging" [preview]="true" />
Environments are configured in the dashboard. Use [preview]="true" to test unpublished changes before making them live.
myop-container (Legacy)
The legacy container component. Use myop-component for new projects.
import { Component } from "@angular/core";
import { MyopContainerComponent } from "@myop/angular";
@Component({
selector: "app-root",
standalone: true,
imports: [MyopContainerComponent],
template: `
<myop-container
[componentId]="'abc123'"
(componentReady)="onReady($event)"
/>
`,
})
export class AppComponent {
onReady(component: any) {
console.log("Ready!", component);
}
}
Type-Safe Event Handlers
Define your CTA payloads for fully typed event handlers:
import { Component } from "@angular/core";
import { MyopComponent } from "@myop/angular";
// Define your component's data and CTA payload types
interface MyData {
items: { id: string; name: string }[];
}
interface RowClickedPayload {
rowIndex: number;
rowData: any;
}
interface ItemSelectedPayload {
itemId: string;
}
interface ExportRequestedPayload {
format: "csv" | "json";
}
@Component({
selector: "app-dashboard",
standalone: true,
imports: [MyopComponent],
template: `
<myop-component
[componentId]="'dashboard-component'"
[data]="data"
(rowClicked)="onRowClicked($event)"
(itemSelected)="onItemSelected($event)"
(action)="onAction($event)"
/>
`,
})
export class DashboardComponent {
data: MyData = {
items: [
{ id: "1", name: "Item 1" },
{ id: "2", name: "Item 2" },
],
};
onRowClicked(payload: RowClickedPayload) {
console.log("Row clicked:", payload.rowIndex);
}
onItemSelected(payload: ItemSelectedPayload) {
console.log("Item selected:", payload.itemId);
}
onAction(event: { action: string; payload: any }) {
console.log(event.action, event.payload);
}
}
Configuration
Preloading Components
Preload components for faster rendering:
import { preloadComponents, isPreloaded } from "@myop/angular";
// Preload multiple components
await preloadComponents(["component-1", "component-2"]);
// Check if a component is preloaded
if (isPreloaded("component-1")) {
console.log("Component is cached and ready");
}
Custom Repository URL
import { setCloudRepositoryUrl } from "@myop/angular";
// Point to a custom Myop server
setCloudRepositoryUrl("https://your-custom-server.com");
Environment Configuration
import { setEnvironment } from "@myop/angular";
// Set default environment for all component loads
setEnvironment("staging");
Local Development
import { enableLocalDev } from "@myop/angular";
// Connect to local Myop development server (localhost:9292)
enableLocalDev();
Advanced: Custom Repository
import { setCloudRepository, getCloudRepository } from "@myop/angular";
import { CloudRepository } from "@myop/sdk/helpers";
// Set a custom CloudRepository instance
const customRepo = new CloudRepository("https://custom-url.com");
setCloudRepository(customRepo);
// Get the current repository
const repo = getCloudRepository();
Loading & Error States
By default, no loader is shown while the component loads. The Myop-branded fallback is displayed automatically on error.
Using the Default Myop Loader
import { Component } from "@angular/core";
import { MyopComponent, MyopLoader } from "@myop/angular";
@Component({
selector: "app-example",
standalone: true,
imports: [MyopComponent, MyopLoader],
template: `
<myop-component [componentId]="'my-component'" [loader]="loaderTpl" [fadeDuration]="300">
</myop-component>
<ng-template #loaderTpl>
<myop-loader></myop-loader>
</ng-template>
`,
})
export class ExampleComponent {}
Custom Loading State
@Component({
selector: "app-example",
standalone: true,
imports: [MyopComponent],
template: `
<myop-component [componentId]="'my-component'" [loader]="loaderTpl" [fadeDuration]="300">
</myop-component>
<ng-template #loaderTpl>
<div class="custom-loader">
<app-spinner />
<p>Loading component...</p>
</div>
</ng-template>
`,
})
export class ExampleComponent {}
Custom Error Fallback
import { Component } from "@angular/core";
import { MyopComponent, MyopFallback } from "@myop/angular";
@Component({
selector: "app-example",
standalone: true,
imports: [MyopComponent, MyopFallback],
template: `
<myop-component [componentId]="'my-component'" [fallback]="fallbackTpl">
</myop-component>
<!-- Custom fallback -->
<ng-template #fallbackTpl>
<div class="error-state">
<p>Failed to load component</p>
<button (click)="retry()">Retry</button>
</div>
</ng-template>
<!-- Or use default Myop fallback explicitly -->
<ng-template #myopFallbackTpl>
<myop-fallback></myop-fallback>
</ng-template>
`,
})
export class ExampleComponent {
retry() {
window.location.reload();
}
}
Using in NgModules
If you're not using standalone components, import in your module:
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { MyopComponent } from "@myop/angular";
import { AppComponent } from "./app.component";
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, MyopComponent],
bootstrap: [AppComponent],
})
export class AppModule {}
API Reference
Exports
| Export | Description |
|---|---|
MyopComponent | Main component for embedding Myop components |
MyopLoader / MyopLoaderComponent | Default Myop-branded loading indicator (opt-in) |
MyopFallback / MyopFallbackComponent | Default Myop-branded error fallback |
preloadComponents | Preload components for faster rendering |
isPreloaded | Check if a component is cached |
enableLocalDev | Enable local development mode |
setCloudRepositoryUrl | Set custom server URL |
setCloudRepository | Set custom CloudRepository instance |
getCloudRepository | Get current CloudRepository instance |
setEnvironment | Set default environment |
License
MIT