@xplortech/apollo-angular
v3.7.0
Published
Angular bindings for Apollo design system web components
Readme
Apollo Angular
Angular bindings for the Apollo design system (@xplortech/apollo-core web components). Use this package in Angular apps for typed inputs, RxJS-backed outputs, and [(ngModel)] / reactive forms on form controls.
Installation
Published as @xplortech/apollo-angular on the public npm registry (same scope as @xplortech/apollo-core and @xplortech/apollo-react).
npm install @xplortech/apollo-angular@xplortech/apollo-core is included as a dependency — you do not need to install both.
Peer dependencies: Angular 19+, RxJS 7+, and TypeScript 5+.
The package exports map exposes the root entry (@xplortech/apollo-angular), documented css/* proxy paths, and ./dist/* passthroughs for backwards compatibility. There is no separate ./server subpath — SSR helpers such as provideApolloSSR() are exported from the root entry.
Import styles once in your app (path may vary with your bundler):
/* Full bundle (backwards compatible) */
@import '@xplortech/apollo-angular/css/apollo.css';
/* Modular two-file pattern + Tailwind v4 companion */
@import '@xplortech/apollo-angular/css/variables/apollo.css';
@import '@xplortech/apollo-angular/css/core.css';
@import '@xplortech/apollo-angular/css/tailwind-theme.css'; /* when using Tailwind v4 with Apollo theme tokens */Usage
The package ships standalone Angular component wrappers (Angular 14+, the default since v17). Custom elements register automatically when you import any wrapper — there is no APP_INITIALIZER setup required.
Standalone components
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { TextValueAccessor, XplButton, XplInput } from '@xplortech/apollo-angular';
@Component({
selector: 'app-root',
standalone: true,
// FormsModule + TextValueAccessor enable [(ngModel)] on xpl-input.
imports: [FormsModule, XplButton, XplInput, TextValueAccessor],
template: `
<xpl-input [(ngModel)]="email" label="Email" type="email"></xpl-input>
<xpl-button variant="primary" (click)="save()">Save</xpl-button>
`,
})
export class AppComponent {
email = '';
save() {}
}NgModule consumers
If your app still uses NgModule, import DIRECTIVES (the full array of wrappers) or individual wrappers into the imports array:
import { NgModule } from '@angular/core';
import { DIRECTIVES } from '@xplortech/apollo-angular';
@NgModule({
declarations: [AppComponent],
imports: [...DIRECTIVES],
})
export class AppModule {}Forms ([(ngModel)] and reactive forms)
These wrappers integrate as Angular ControlValueAccessor implementations:
| Component | Form value | Update event (internal) | Value accessor |
|---------------|---------------|-------------------------|-----------------------|
| XplInput | value | valueChange | TextValueAccessor |
| XplCheckbox | checked | checkboxChange | BooleanValueAccessor|
| XplRadio | selectedValue | radioChange | RadioValueAccessor |
| XplToggle | checked | toggleChange | BooleanValueAccessor|
| XplSelect | selectedValues | changeEvent | SelectValueAccessor |
Standalone imports: each form control's value accessor is a separate standalone directive. To use
[(ngModel)]orformControlNameyou must import the matching value accessor alongside the component (see below), or import the fullDIRECTIVESarray (which includes every wrapper and every value accessor).NgModuleconsumers that import...DIRECTIVESget form binding automatically.
Template-driven forms
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import {
BooleanValueAccessor,
TextValueAccessor,
XplCheckbox,
XplInput,
XplToggle,
} from '@xplortech/apollo-angular';
@Component({
selector: 'app-profile',
standalone: true,
imports: [
FormsModule,
XplCheckbox,
XplInput,
XplToggle,
// Value accessors register NG_VALUE_ACCESSOR on the hosts above.
TextValueAccessor,
BooleanValueAccessor,
],
template: `
<xpl-input [(ngModel)]="name" label="Name"></xpl-input>
<xpl-checkbox [(ngModel)]="agreed" label="I agree"></xpl-checkbox>
<xpl-toggle [(ngModel)]="enabled">Enabled</xpl-toggle>
`,
})
export class ProfileComponent {
name = '';
agreed = false;
enabled = false;
}Reactive forms
import { Component } from '@angular/core';
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
import {
BooleanValueAccessor,
TextValueAccessor,
XplInput,
XplToggle,
} from '@xplortech/apollo-angular';
@Component({
selector: 'app-settings',
standalone: true,
imports: [
ReactiveFormsModule,
XplInput,
XplToggle,
TextValueAccessor,
BooleanValueAccessor,
],
template: `
<form [formGroup]="form">
<xpl-input formControlName="name" label="Name"></xpl-input>
<xpl-toggle formControlName="enabled">Enabled</xpl-toggle>
</form>
`,
})
export class SettingsComponent {
form = this.fb.group({ name: '', enabled: false });
constructor(private fb: FormBuilder) {}
}Tip: to avoid importing individual value accessors, import the whole
DIRECTIVESarray in a standalone component'simports— it registers every wrapper and value accessor at once.
Specialized input types: <xpl-input type="date">, type="time", type="phone", type="color", and type="file" all work with [(ngModel)]. Internally, xpl-input renders a sub-component (e.g. xpl-input-date) and forwards its events. Prefer <xpl-input type="date" [(ngModel)]="val"> over using the sub-components directly.
Events and complex props
Stencil @Event() names are exposed as Angular @Output() EventEmitters and emit CustomEvent instances. Use .detail to read the payload:
<xpl-table
[data]="rows"
[columns]="cols"
(tableSelect)="onSelect($event.detail)"
></xpl-table>Pass objects and arrays directly as [propName] bindings — Angular forwards them as DOM properties:
<xpl-table [data]="rows" [columns]="cols"></xpl-table>Server-side rendering (Angular Universal)
@stencil/angular-output-target has no hydrateModule option (unlike React and Vue). For Angular Universal, import provideApolloSSR() from the package root — there is no separate @xplortech/apollo-angular/server entry. Add it to your server config alongside provideServerRendering():
// app.config.server.ts
import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';
import { provideServerRendering } from '@angular/platform-server';
import { provideApolloSSR } from '@xplortech/apollo-angular';
import { appConfig } from './app.config';
const serverConfig: ApplicationConfig = {
providers: [provideServerRendering(), provideApolloSSR()],
};
export const config = mergeApplicationConfig(appConfig, serverConfig);Use the same standalone imports as in the browser (XplButton, XplInput, TextValueAccessor, etc.). SSR HTML will include Stencil-serialized markup on xpl-* hosts. provideApolloSSR() syncs Angular property bindings (including [(ngModel)]) before serialization and sets ngSkipHydration on each host so provideClientHydration() does not fight Stencil's server markup. See the SSR guide for React, Vue, and verification steps.
Further reading
- Apollo repo
- Core components and behavior:
@xplortech/apollo-core/ Storybook in this monorepo - Stencil Angular output target docs
