- Getting Started
- The Basics
- Concepts
- SuperNative
-
EDGE Components
- Introduction
- Activity Indicator
- Badge
- Bottom Navigation
- Bottom Sheet
- Button
- Button Group
- Canvas
- Carousel
- Checkbox
- Chip
- Column
- Divider
- Gesture Area
- Icon
- Icons
- Image
- Layout & Styling
- List
- Menus
- Modal
- Pressable
- Progress Bar
- Radio Group
- Row
- Scroll View
- Select
- Shapes
- Side Navigation
- Slider
- Spacer
- Stack
- Tab Row
- Text
- Text Input
- Toggle
- Top Bar
- Virtual List
- Web View
- Plugins
- Testing
- Architecture
You're viewing pre-release documentation — version 4.x is in beta
Features, APIs and behaviour may change before the stable release. View the stable version (3.x)
Data Binding
Overview#
native:model two-way binds a native input to a public property on your component — the native equivalent of
Livewire's wire:model. Type into a field, toggle a switch, drag a slider, and the bound property updates on the
PHP side; change the property in PHP and the control reflects it on the next render.
<native:text-input native:model="name" placeholder="Your name" />
class ProfileScreen extends NativeComponent{ public string $name = '';}
That's the whole contract: no @press, no manual onChange handler. The value lives in $name, and every
render sees the current value.
Supported controls#
Any input-style EDGE component binds with native:model:
<native:text-input>— string<native:toggle>/<native:checkbox>— boolean<native:slider>— float<native:radio-group>/<native:select>— string<native:chip>/<native:button-group>— selection<native:tab-row>— int (active index)
The bound value is coerced to match the control: a toggle syncs a bool, a slider a float, a tab row an int,
text and pickers a string. Declare your property with the matching type.
Sync modifiers#
By default the property updates on every change (each keystroke). Modifiers change when the sync fires — useful for text inputs where syncing on every character is wasteful:
| Modifier | When it syncs |
|---|---|
native:model (or .live) |
On every change — the default. |
native:model.blur |
Only when the field loses focus. |
native:model.lazy |
Alias for .blur. |
native:model.debounce.300ms |
After the user stops changing it for the given delay. |
{{-- Sync only when the user leaves the field --}}<native:text-input native:model.blur="email" /> {{-- Sync 500ms after typing stops --}}<native:text-input native:model.debounce.500ms="search" />
Reacting to changes#
When a bound property changes from the UI, the framework fires the matching
updated{Property}() hook, passing the new value — the place to run
validation or trigger side effects:
public string $search = '';public array $results = []; public function updatedSearch(string $value): void{ $this->results = Product::search($value)->get()->all();}
A change also invalidates every #[Computed] value, so anything derived from the
property recomputes on the next frame. Together these let you keep components declarative: bind inputs to
properties, derive the rest with computed methods, and let the UI re-render itself.
Without binding#
native:model is sugar. If you'd rather handle the event yourself — to transform the value, or to bind to
something other than a public property — set the value and change handler directly:
<native:text-input :value="$name" @change="rename" />
public function rename(string $value): void{ $this->name = trim($value);}
in no time