Angular guide
The Angular adapter drives the same native Fabric engine as React and Vue
through a custom Renderer2/RendererFactory2 — Angular’s own
framework-agnostic rendering seam. Bootstrap is DOM-less: no
platform-browser, no zone.js. Angular renderer operations become engine
mutations, then Fabric commits real native views.
The examples/angular canary — the same component surface and engine as
the React and Vue canaries, driven through Renderer2 instead.
Minimal component
Section titled “Minimal component”import { Component } from '@angular/core';import { Pressable, Text, View } from '@symbiote-native/angular';import './app.css';
@Component({ selector: 'app-root', standalone: true, imports: [Pressable, Text, View], template: ` <View class="root"> <Pressable (press)="increment()"> <Text class="label">Count is {{ count }}</Text> </Pressable> </View> `,})export class App { count = 0;
increment(): void { this.count += 1; }}.root { flex: 1; align-items: center; justify-content: center; }.label { font-size: 24px; }StyleSheet.create works identically if you’d rather keep style objects
inline instead of a CSS file — see the Styling guide
for both paths.
Angular contract
Section titled “Angular contract”Angular is a standalone-components-only adapter:
- every SymbioteNative component is
standalone: true— import it directly in the consuming component’simportsarray, there is noNgModule; - every component event is a real Angular
@Output()EventEmitter—(press)="onTap($event)",(longPress)="...",(hoverIn)="...",(valueChange)="...",(accessibilityAction)="...", and so on acrossPressable,Button,Touchable*,Switch,TextInput,Modal, and every other component. An event nobody templates costs nothing: an unbound(longPress)still skips arming the long-press timer, the same as an absent callback prop used to.TextInputis the one component with two outputs for what React/Vue fold into one callback:(valueChange)stays text-only (anEventEmittercarries one value, and text-only keeps[(value)]two-way binding working) while(change)is a second, separate output for the raw native event; - the one permanent exception is the scroll family —
onScroll,onScrollBeginDrag,onScrollEndDrag,onMomentumScrollBegin,onMomentumScrollEndstay callback inputs ([onScroll]="handler") onScrollViewand the list components, because they can carry anAnimated.event(...)marker for native-driven scroll and@Output()can’t bind an arbitrary value, only a template listener expression; - component selectors accept both a PascalCase alias and the
symbiote-*prefix (selector: 'Pressable, symbiote-pressable'), so templates read like<Pressable>/<View>/<Text>while the underlying primitive hosts staysymbiote-view/symbiote-text/ etc.; - imperative handles use
@ViewChild(..., { read: ElementRef })— thenativeElementis the SymbioteNative host node, not a DOM element; - change detection is zoneless: the adapter runs on Angular’s own
ApplicationRef.tick(), wired in via the internalɵprovideZonelessChangeDetectionInternal()helper rather than the publicprovideZonelessChangeDetection()(which assumes aplatform-browserbootstrap this DOM-less renderer doesn’t use), so template updates batch the same way Vue’srequestCommit()does, without zone.js patching Hermes globals.
Read the exact API surface in the Angular API reference.