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};