npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@servlyadmin/runtime-angular

v0.1.39

Published

Angular wrapper for Servly runtime components

Readme

@servlyadmin/runtime-angular

Angular wrapper for Servly runtime renderer. Render Servly components in your Angular applications with full slot support, state management, and reactive updates.

Installation

npm install @servlyadmin/runtime-angular
# or
yarn add @servlyadmin/runtime-angular
# or
pnpm add @servlyadmin/runtime-angular

Requirements

  • Angular 14.0.0 or higher
  • @servlyadmin/runtime-core (installed automatically)

Setup

Import the ServlyModule in your Angular module:

import { NgModule } from '@angular/core';
import { ServlyModule } from '@servlyadmin/runtime-angular';

@NgModule({
  imports: [
    ServlyModule,
    // ... other imports
  ],
})
export class AppModule {}

Or for standalone components:

import { Component } from '@angular/core';
import { ServlyComponent, ServlySlotDirective } from '@servlyadmin/runtime-angular';

@Component({
  standalone: true,
  imports: [ServlyComponent, ServlySlotDirective],
  // ...
})
export class MyComponent {}

Quick Start

import { Component } from '@angular/core';

@Component({
  selector: 'app-example',
  template: `
    <servly-component
      id="my-component"
      [props]="{ title: 'Hello World' }"
      (load)="onLoad($event)"
      (error)="onError($event)"
    ></servly-component>
  `,
})
export class ExampleComponent {
  onLoad(data: any) {
    console.log('Component loaded:', data);
  }

  onError(error: Error) {
    console.error('Failed to load:', error);
  }
}

API Reference

ServlyComponent Inputs

| Input | Type | Default | Description | |-------|------|---------|-------------| | id | string | required | Component ID from the registry | | version | string | 'latest' | Version specifier | | props | object | {} | Props to pass to the component | | state | object | undefined | Additional state for bindings | | context | object | undefined | Additional context for bindings | | eventHandlers | object | undefined | Event handlers keyed by element ID | | cacheStrategy | 'memory' \| 'localStorage' \| 'none' | 'memory' | Caching strategy | | retryConfig | object | undefined | Retry configuration | | forceRefresh | boolean | false | Force refresh from registry | | showSkeleton | boolean | true | Show loading skeleton | | enableStateManager | boolean | false | Enable state management | | initialState | object | undefined | Initial state |

Outputs

| Output | Type | Description | |--------|------|-------------| | load | EventEmitter<ComponentData> | Emitted on successful load | | error | EventEmitter<Error> | Emitted on load failure | | slotsReady | EventEmitter<Record<string, HTMLElement>> | Emitted when slots are ready | | stateChange | EventEmitter<StateChangeEvent> | Emitted on state change | | ready | EventEmitter<void> | Emitted when fully rendered |

Slot Directive

Use the servlySlot directive to define slot content:

<servly-component id="my-component">
  <ng-template servlySlot="header">
    <h1>Custom Header</h1>
  </ng-template>
  
  <ng-template servlySlot="footer">
    <p>Custom Footer</p>
  </ng-template>
</servly-component>

Custom Loading/Error States

<servly-component id="my-component">
  <!-- Custom loading state -->
  <div servlyFallback>
    <mat-spinner></mat-spinner>
    <p>Loading component...</p>
  </div>
  
  <!-- Custom error state -->
  <div servlyError>
    <mat-icon>error</mat-icon>
    <p>Failed to load component</p>
  </div>
</servly-component>

Advanced Usage

With State Management

import { Component } from '@angular/core';
import { StateChangeEvent } from '@servlyadmin/runtime-angular';

@Component({
  selector: 'app-counter',
  template: `
    <servly-component
      id="counter-component"
      [props]="{ count: count }"
      [enableStateManager]="true"
      [initialState]="{ count: 0 }"
      (stateChange)="onStateChange($event)"
    ></servly-component>
  `,
})
export class CounterComponent {
  count = 0;

  onStateChange(event: StateChangeEvent) {
    if (event.key === 'count') {
      this.count = event.value;
    }
  }
}

Using ServlyStateService

import { Component, OnInit, OnDestroy } from '@angular/core';
import { ServlyStateService } from '@servlyadmin/runtime-angular';

@Component({
  selector: 'app-stateful',
  template: `...`,
})
export class StatefulComponent implements OnInit, OnDestroy {
  private unsubscribe?: () => void;

  constructor(private servlyState: ServlyStateService) {}

  ngOnInit() {
    // Initialize state
    this.servlyState.initialize({ user: null });
    
    // Subscribe to changes
    this.unsubscribe = this.servlyState.subscribe((event) => {
      console.log('State changed:', event);
    });
  }

  ngOnDestroy() {
    this.unsubscribe?.();
  }

  updateUser(user: any) {
    this.servlyState.set('user', user);
  }

  getUser() {
    return this.servlyState.get('user');
  }
}

With Event Handlers

import { Component } from '@angular/core';

@Component({
  selector: 'app-form',
  template: `
    <servly-component
      id="form-component"
      [eventHandlers]="handlers"
    ></servly-component>
  `,
})
export class FormComponent {
  handlers = {
    'submit-btn': {
      onClick: (event: Event) => {
        console.log('Submit clicked!');
        this.handleSubmit();
      },
    },
    'email-input': {
      onChange: (event: Event) => {
        const input = event.target as HTMLInputElement;
        console.log('Email:', input.value);
      },
    },
  };

  handleSubmit() {
    // Handle form submission
  }
}

Accessing Component Methods

import { Component, ViewChild } from '@angular/core';
import { ServlyComponent } from '@servlyadmin/runtime-angular';

@Component({
  selector: 'app-example',
  template: `
    <servly-component #servly id="my-component"></servly-component>
    <button (click)="reload()">Reload</button>
  `,
})
export class ExampleComponent {
  @ViewChild('servly') servlyComponent!: ServlyComponent;

  reload() {
    // Access component methods
    this.servlyComponent.retry();
  }

  getSlotElement(name: string) {
    return this.servlyComponent.getSlotElement(name);
  }

  getSlotNames() {
    return this.servlyComponent.getSlotNames();
  }
}

Version Specifiers

<!-- Exact version -->
<servly-component id="my-component" version="1.2.3"></servly-component>

<!-- Caret range -->
<servly-component id="my-component" version="^1.0.0"></servly-component>

<!-- Tilde range -->
<servly-component id="my-component" version="~1.2.0"></servly-component>

<!-- Latest -->
<servly-component id="my-component" version="latest"></servly-component>

Reactive Props

import { Component } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Component({
  selector: 'app-reactive',
  template: `
    <servly-component
      id="my-component"
      [props]="props$ | async"
    ></servly-component>
  `,
})
export class ReactiveComponent {
  props$ = new BehaviorSubject({ count: 0 });

  increment() {
    const current = this.props$.value;
    this.props$.next({ count: current.count + 1 });
  }
}

TypeScript Support

Full TypeScript support is included:

import type {
  ComponentData,
  BindingContext,
  StateChangeEvent,
  CacheStrategy,
  RetryConfig,
} from '@servlyadmin/runtime-angular';

Re-exported Utilities

import {
  // Fetching
  fetchComponent,
  prefetchComponents,
  setRegistryUrl,
  
  // Caching
  invalidateCache,
  clearAllCaches,
  
  // Version utilities
  parseVersion,
  compareVersions,
  
  // State management
  StateManager,
  getValueByPath,
  
  // Event system
  EventSystem,
  getEventSystem,
} from '@servlyadmin/runtime-angular';

License

MIT