Skip to main content

a2ui_base/components/
text_field.rs

1//! TextField component behavior — framework-agnostic `handle_event`.
2
3use crate::event::{EventResult, InputEvent, InputKey};
4use crate::model::component_context::ComponentContext;
5use crate::protocol::common_types::DynamicString;
6
7/// Handle a key-press for a TextField (appends chars / backspaces the bound string).
8pub fn handle_event(ctx: &ComponentContext, event: &InputEvent) -> Option<EventResult> {
9    let comp_model = ctx.components.get(&ctx.component_id)?;
10
11    // Get the value binding path.
12    let value_ds = comp_model.get_property::<DynamicString>("value")?;
13    let binding = match value_ds {
14        DynamicString::Binding(b) => b,
15        _ => return None,
16    };
17
18    let current =
19        ctx.data_context
20            .resolve_dynamic_string(&DynamicString::Binding(binding.clone()));
21
22    match event {
23        InputEvent::KeyPress { key: InputKey::Char(c) } => {
24            let new_value = format!("{}{}", current, c);
25            Some(EventResult::DataUpdate {
26                path: binding.path.clone(),
27                value: serde_json::Value::String(new_value),
28            })
29        }
30        InputEvent::KeyPress {
31            key: InputKey::Backspace,
32        } => {
33            let new_value = if let Some((idx, _)) = current.char_indices().next_back() {
34                &current[..idx]
35            } else {
36                ""
37            }
38            .to_string();
39            Some(EventResult::DataUpdate {
40                path: binding.path.clone(),
41                value: serde_json::Value::String(new_value),
42            })
43        }
44        _ => None,
45    }
46}