zng/
data_context.rs

1#![cfg(feature = "data_context")]
2
3//! Data context service and properties.
4//!
5//! The [`data`](fn@data) property can be set on a widget to any type that can be used in variables ([`VarValue`]). The
6//! [`DATA`] service can then be used on the widget or descendant widgets to retrieve the data and to set validation annotations
7//! about the data.
8//!
9//! The example below demonstrates a simple [MVVM] implementation using the data context to share the view-model instance
10//! with all widgets in the view. The example also uses the data annotations API to show data validation errors.
11//!
12//! [MVVM]: https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel
13//!
14//! ```
15//! # fn main() { }
16//! mod view {
17//!     use crate::view_model::*;
18//!     use zng::{data_context, prelude::*, window::WindowRoot};
19//!
20//!     pub fn window() -> WindowRoot {
21//!         Window! {
22//!             // set data context for entire window, using `var` to be read-write.
23//!             data = var(ViewModel::new(crate::model::connect()));
24//!
25//!             // bind title from data context.
26//!             title = DATA.req::<ViewModel>().map(|vm| vm.title());
27//!             child = content();
28//!         }
29//!     }
30//!
31//!     fn content() -> UiNode {
32//!         // `req` panics if context is not set to the same type.
33//!         let vm = DATA.req::<ViewModel>();
34//!         Container! {
35//!             child = TextInput! {
36//!                 txt = vm.map_bidi_modify(|vm| vm.new_item(), |v, vm| vm.set_new_item(v.clone()));
37//!
38//!                 // FieldStyle shows data errors.
39//!                 style_fn = style_fn!(|_| zng::text_input::FieldStyle!());
40//!                 data_context::data_error = vm.map(|vm| vm.new_item_error());
41//!             };
42//!             child_bottom = Button! {
43//!                 child = Text!("Submit");
44//!                 widget::enabled = vm.map(|vm| !vm.new_item().is_empty());
45//!                 on_click = hn!(|_| vm.modify(|vm| vm.submit()));
46//!             };
47//!             child_spacing = 5;
48//!             padding = 5;
49//!         }
50//!     }
51//! }
52//!
53//! mod view_model {
54//!     use crate::model::Model;
55//!     use zng::text::*;
56//!
57//!     #[derive(Clone, Debug, PartialEq)]
58//!     pub struct ViewModel {
59//!         model: Model,
60//!         new_item: Txt,
61//!         new_item_error: Txt,
62//!     }
63//!     impl ViewModel {
64//!         pub fn new(model: Model) -> Self {
65//!             Self {
66//!                 model,
67//!                 new_item: Txt::from(""),
68//!                 new_item_error: Txt::from(""),
69//!             }
70//!         }
71//!
72//!         pub fn title(&self) -> Txt {
73//!             formatx!("App - {} entries", self.model.read().len())
74//!         }
75//!
76//!         pub fn new_item(&self) -> Txt {
77//!             self.new_item.clone()
78//!         }
79//!         pub fn set_new_item(&mut self, new_item: Txt) {
80//!             self.new_item_error = "".into();
81//!             self.new_item = new_item;
82//!         }
83//!
84//!         pub fn new_item_error(&self) -> Txt {
85//!             self.new_item_error.clone()
86//!         }
87//!
88//!         pub fn submit(&mut self) {
89//!             match self.new_item.parse::<u32>() {
90//!                 Ok(item) => {
91//!                     self.model.write().push(item);
92//!                     self.set_new_item(Txt::from(""));
93//!                 }
94//!                 Err(e) => self.new_item_error = e.to_txt(),
95//!             }
96//!         }
97//!     }
98//! }
99//!
100//! mod model {
101//!     use zng::{task::parking_lot::RwLock, var::ArcEq};
102//!
103//!     pub type Model = ArcEq<RwLock<Vec<u32>>>;
104//!
105//!     pub fn connect() -> ArcEq<RwLock<Vec<u32>>> {
106//!         ArcEq::new(RwLock::new(vec![]))
107//!     }
108//! }
109//! ```
110//!
111//! [`data`]: fn@data
112//! [`VarValue`]: crate::var::VarValue
113//!
114//! # Full API
115//!
116//! See [`zng_wgt_data`] for the full API.
117
118pub use zng_wgt_data::{
119    DATA, DataNote, DataNoteHandle, DataNoteLevel, DataNoteValue, DataNotes, data, data_error, data_error_color, data_info,
120    data_info_color, data_note, data_warn, data_warn_color, extend_data_note_colors, get_data_error, get_data_error_txt, get_data_info,
121    get_data_info_txt, get_data_notes, get_data_notes_top, get_data_warn, get_data_warn_txt, has_data_error, has_data_info, has_data_notes,
122    has_data_warn, replace_data_note_colors, with_data_note_color,
123};