Events
Native Fabric events come back to the engine. Each adapter then exposes them in
that framework’s idiom: React callback props, Vue typed emits (plus v-model
on controlled components), and Angular real @Output() EventEmitters — with
one permanent exception, the scroll-family events, which stay callback inputs
(see the caveat below).
Same event, different framework shape
Section titled “Same event, different framework shape”React:
<Switch value={enabled} onValueChange={setEnabled} /><TextInput value={name} onValueChange={setName} /><Pressable onPress={() => setCount(count + 1)} />Vue — typed emits, or v-model on the controlled components that support it:
<Switch v-model="enabled" /><TextInput v-model="name" /><Pressable @press="count++" />Angular — real @Output() EventEmitters everywhere, including Switch and
TextInput:
template: ` <Switch [value]="enabled" (valueChange)="setEnabled($event)" /> <TextInput [value]="name" (valueChange)="setName($event)" /> <Pressable (press)="count = count + 1" />`The payload is the same concept. The public API is framework-shaped.
Passthrough events vs adapter events
Section titled “Passthrough events vs adapter events”Some events are native passthrough events. They travel through the engine as
onX listeners and should not be declared as Vue emits unless the Vue component
actually consumes and re-emits them.
Other events are adapter-level conveniences. Examples:
| Concept | React | Vue | Angular |
|---|---|---|---|
| Press | onPress |
@press |
(press) |
| Switch value | onValueChange(value, event) |
@value-changeor v-model |
(valueChange) (value only) |
| Text input text | onValueChange(text, event) |
@value-changeor v-model |
(valueChange) (text only) |
| Text input raw event | (same callback, 2nd arg) | (same emit, 2nd arg) | (change) (separate output) |
React and Vue merged TextInput’s old onChangeText/onChange pair into one
onValueChange(text, event) callback — there’s only ever one underlying
native event. Angular keeps two separate @Output()s instead, because an
EventEmitter carries exactly one value: valueChange stays text-only (so
[(value)] two-way binding keeps working) and change is a second output
for the raw event. Switch follows the same shape one level simpler: React’s
onValueChange and Vue’s @value-change both receive the native event as a
second argument, but Angular’s valueChange stays single-value (just the
boolean) since there’s no second output to split it into.
This split matters because Vue removes declared emit listeners from attrs. If a native passthrough listener is declared as an emit by mistake, the engine may never see it.
Controlled components
Section titled “Controlled components”Switch and TextInput follow React Native’s controlled-component rules. If the
native view reports a new value but the parent does not update the value prop,
SymbioteNative commands native back to the JavaScript value.
That correction logic is shared in @symbiote-native/components; React, Vue, and
Angular each only wire it to their own lifecycle systems.