- Getting Started
- Architecture
- The Basics
- Digging Deeper
-
EDGE Components
- Introduction
- Accordion
- Activity Indicator
- Badge
- Bottom Navigation
- Bottom Sheet
- Button
- Button Group
- Canvas
- Carousel
- Checkbox
- Chip
- Column
- Divider
- Floating Action Button
- Gesture Area
- Icon
- Image
- Lazy Grid
- Layout & Styling
- List
- Menus
- Modal
- Pressable
- Progress Bar
- Radio Group
- Pager
- Refreshable
- Row
- Scroll View
- Select
- Shapes
- Side Navigation
- Slider
- Spacer
- Stack
- Tab Row
- Text
- Text Input
- Toggle
- Top Bar
- Virtual List
- Web View
- Plugins
- Testing
- Publishing Your App
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:outlined-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:outlined-text-input>,<native:filled-text-input>and<native:bare-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. |
For text the user types freely, prefer a short debounce such as native:model.debounce.150ms. A live binding sends
every keystroke to PHP, and when someone types quickly an earlier keystroke's value can come back after later ones and
overwrite them, so characters appear to vanish. See
Text Input › Choosing a sync mode.
{{-- Sync only when the user leaves the field --}}<native:outlined-text-input native:model.blur="email" /> {{-- Sync 500ms after typing stops --}}<native:outlined-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:outlined-text-input :value="$name" @change="rename" />
public function rename(string $value): void{ $this->name = trim($value);}
in no time