Skip to main content

State

Struct State 

Source
pub struct State<T> { /* private fields */ }
Expand description

Searchable select state.

The inner state keeps the current search query and filtered Material menu options. The public state also stores the original options so selected values and typed input can be mirrored by the demo/application state without replacing user-entered text on blur.

Implementations§

Source§

impl<T> State<T>
where T: Display + Clone,

Source

pub fn new(options: Vec<T>) -> Self

Creates a new State for a combobox with the given list of options.

Source

pub fn with_selection(options: Vec<T>, selection: Option<&T>) -> Self

Creates a new State for a combobox with the given list of options and selected value.

Examples found in repository?
examples/showcase/app.rs (lines 204-207)
194    fn default() -> Self {
195        Self {
196            navigation: navigation::NavigationState::new(ShowcasePage::Inputs),
197            window_size: Size::new(1080.0, 980.0),
198            count: 0,
199            note: String::new(),
200            editor_content: material::widget::text_editor::Content::with_text(
201                "Material 3 multi-line text editor",
202            ),
203            select_choice: Some("Assist"),
204            combobox_options: material::widget::combobox::State::with_selection(
205                vec!["Assist", "Suggestion", "Filter"],
206                Some(&"Suggestion"),
207            ),
208            combobox_choice: Some("Suggestion"),
209            combobox_input: String::new(),
210            search_query: String::new(),
211            date_picker: material::widget::picker::DatePickerState::new(
212                material::widget::picker::Date::new(2026, 7, 4),
213            ),
214            date_range_picker: material::widget::picker::DateRangePickerState::new(
215                material::widget::picker::Date::new(2026, 7, 4),
216                material::widget::picker::Date::new(2026, 7, 10),
217            ),
218            time_picker: material::widget::picker::TimePickerState::new(14, 30, false),
219            progress: 42.0,
220            enabled: true,
221            radio_choice: Some(RadioChoice::Standard),
222            segment_choice: SegmentChoice::List,
223            segment_state: material::widget::segmented_button::State::new(
224                SegmentChoice::List.index(),
225            ),
226            primary_tab: TabChoice::Inputs,
227            primary_tab_state: material::widget::tabs::State::new(TabChoice::Inputs.index()),
228            secondary_tab: TabChoice::Controls,
229            secondary_tab_state: material::widget::tabs::State::new(TabChoice::Controls.index()),
230            progress_animation: material::widget::progress_bar::IndeterminateState::new(
231                Instant::now(),
232            ),
233            alert_dialog: material::widget::dialog::Transition::default(),
234            snackbar: material::widget::snackbar::Transition::default(),
235            theme_controller: theme_picker::ThemeController::default(),
236        }
237    }
Source

pub fn options(&self) -> &[T]

Returns the original options.

Source

pub fn push(&mut self, new_option: T)

Pushes a new option.

Source

pub fn into_options(self) -> Vec<T>

Returns ownership of the original options.

Source

pub fn set_input(&mut self, input: impl Into<String>)

Synchronizes the internal query with the latest user input.

Examples found in repository?
examples/showcase/app.rs (line 293)
254fn update(state: &mut Showcase, message: Message) -> Task<Message> {
255    match message {
256        #[cfg(any(target_arch = "wasm32", test))]
257        Message::CjkCoreFontFinished => load_cjk_regional_font(),
258        #[cfg(any(target_arch = "wasm32", test))]
259        Message::CjkRegionalFontFinished => Task::none(),
260        Message::Navigate(page) => {
261            state
262                .navigation
263                .select(page, Instant::now(), state.adaptive_navigation_layout());
264            Task::none()
265        }
266        Message::Increment => {
267            state.count += 1;
268            Task::none()
269        }
270        Message::Decrement => {
271            state.count -= 1;
272            Task::none()
273        }
274        Message::TextChanged(note) => {
275            state.note = note;
276            Task::none()
277        }
278        Message::EditorAction(action) => {
279            state.editor_content.perform(action);
280            Task::none()
281        }
282        Message::SelectChanged(choice) => {
283            state.select_choice = Some(choice);
284            Task::none()
285        }
286        Message::ComboboxSelected(choice) => {
287            state.combobox_choice = Some(choice);
288            state.combobox_input.clear();
289            state.combobox_options.set_selection(Some(&choice));
290            Task::none()
291        }
292        Message::ComboboxInputChanged(input) => {
293            state.combobox_options.set_input(input.clone());
294            state.combobox_input = input;
295            state.combobox_choice = None;
296            Task::none()
297        }
298        Message::SearchChanged(query) => {
299            state.search_query = query;
300            Task::none()
301        }
302        Message::DatePickerChanged(action) => state.date_picker.update_and_scroll(action),
303        Message::DateRangePickerChanged(action) => {
304            state.date_range_picker.update_and_scroll(action)
305        }
306        Message::TimePickerChanged(action) => {
307            state.time_picker.update(action);
308            Task::none()
309        }
310        Message::SliderChanged(progress) => {
311            state.progress = progress;
312            Task::none()
313        }
314        Message::EnabledChanged(enabled) => {
315            state.enabled = enabled;
316            Task::none()
317        }
318        Message::ChoiceSelected(choice) => {
319            state.radio_choice = Some(choice);
320            Task::none()
321        }
322        Message::SegmentSelected(choice) => {
323            state.segment_choice = choice;
324            state.segment_state.select(choice.index(), Instant::now());
325            Task::none()
326        }
327        Message::PrimaryTabSelected(choice) => {
328            state.primary_tab = choice;
329            state.primary_tab_state.select(
330                choice.index(),
331                Instant::now(),
332                material::widget::tabs::Variant::Primary,
333            );
334            Task::none()
335        }
336        Message::SecondaryTabSelected(choice) => {
337            state.secondary_tab = choice;
338            state.secondary_tab_state.select(
339                choice.index(),
340                Instant::now(),
341                material::widget::tabs::Variant::Secondary,
342            );
343            Task::none()
344        }
345        Message::MenuPressed => {
346            state.navigation.toggle_menu_now();
347            Task::none()
348        }
349        Message::DialogOpened => {
350            state.alert_dialog.show(Instant::now());
351            Task::none()
352        }
353        Message::DialogDismissed => {
354            state.alert_dialog.dismiss(Instant::now());
355            Task::none()
356        }
357        Message::DialogConfirmed => {
358            state.alert_dialog.dismiss(Instant::now());
359            state.count += 1;
360            Task::none()
361        }
362        Message::ShowSnackbar => {
363            state.snackbar.show(Instant::now());
364            Task::none()
365        }
366        Message::SnackbarUndo => {
367            state.count -= 1;
368            state.snackbar.dismiss(Instant::now());
369            Task::none()
370        }
371        Message::WindowResized(size) => {
372            state.window_size = size;
373            Task::none()
374        }
375        Message::ThemeChanged(action) => {
376            state.theme_controller.update(
377                action,
378                state.window_size,
379                theme_picker::bottom_margin(state.adaptive_navigation_layout()),
380                Instant::now(),
381            );
382            Task::none()
383        }
384        Message::Frame(now) => {
385            let _ = state.theme_controller.advance(now);
386            let _ = state.navigation.advance(now);
387            let _ = state.segment_state.advance(now);
388            let _ = state.primary_tab_state.advance(now);
389            let _ = state.secondary_tab_state.advance(now);
390            state.progress_animation.advance(now);
391            let _ = state.alert_dialog.advance(now);
392            let _ = state.snackbar.advance(now);
393            let _ = state.date_picker.advance(now);
394            let _ = state.date_range_picker.advance(now);
395            let _ = state.time_picker.advance(now);
396            Task::none()
397        }
398    }
399}
Source

pub fn set_selection(&mut self, selection: Option<&T>)

Synchronizes the internal query with the selected option.

Examples found in repository?
examples/showcase/app.rs (line 289)
254fn update(state: &mut Showcase, message: Message) -> Task<Message> {
255    match message {
256        #[cfg(any(target_arch = "wasm32", test))]
257        Message::CjkCoreFontFinished => load_cjk_regional_font(),
258        #[cfg(any(target_arch = "wasm32", test))]
259        Message::CjkRegionalFontFinished => Task::none(),
260        Message::Navigate(page) => {
261            state
262                .navigation
263                .select(page, Instant::now(), state.adaptive_navigation_layout());
264            Task::none()
265        }
266        Message::Increment => {
267            state.count += 1;
268            Task::none()
269        }
270        Message::Decrement => {
271            state.count -= 1;
272            Task::none()
273        }
274        Message::TextChanged(note) => {
275            state.note = note;
276            Task::none()
277        }
278        Message::EditorAction(action) => {
279            state.editor_content.perform(action);
280            Task::none()
281        }
282        Message::SelectChanged(choice) => {
283            state.select_choice = Some(choice);
284            Task::none()
285        }
286        Message::ComboboxSelected(choice) => {
287            state.combobox_choice = Some(choice);
288            state.combobox_input.clear();
289            state.combobox_options.set_selection(Some(&choice));
290            Task::none()
291        }
292        Message::ComboboxInputChanged(input) => {
293            state.combobox_options.set_input(input.clone());
294            state.combobox_input = input;
295            state.combobox_choice = None;
296            Task::none()
297        }
298        Message::SearchChanged(query) => {
299            state.search_query = query;
300            Task::none()
301        }
302        Message::DatePickerChanged(action) => state.date_picker.update_and_scroll(action),
303        Message::DateRangePickerChanged(action) => {
304            state.date_range_picker.update_and_scroll(action)
305        }
306        Message::TimePickerChanged(action) => {
307            state.time_picker.update(action);
308            Task::none()
309        }
310        Message::SliderChanged(progress) => {
311            state.progress = progress;
312            Task::none()
313        }
314        Message::EnabledChanged(enabled) => {
315            state.enabled = enabled;
316            Task::none()
317        }
318        Message::ChoiceSelected(choice) => {
319            state.radio_choice = Some(choice);
320            Task::none()
321        }
322        Message::SegmentSelected(choice) => {
323            state.segment_choice = choice;
324            state.segment_state.select(choice.index(), Instant::now());
325            Task::none()
326        }
327        Message::PrimaryTabSelected(choice) => {
328            state.primary_tab = choice;
329            state.primary_tab_state.select(
330                choice.index(),
331                Instant::now(),
332                material::widget::tabs::Variant::Primary,
333            );
334            Task::none()
335        }
336        Message::SecondaryTabSelected(choice) => {
337            state.secondary_tab = choice;
338            state.secondary_tab_state.select(
339                choice.index(),
340                Instant::now(),
341                material::widget::tabs::Variant::Secondary,
342            );
343            Task::none()
344        }
345        Message::MenuPressed => {
346            state.navigation.toggle_menu_now();
347            Task::none()
348        }
349        Message::DialogOpened => {
350            state.alert_dialog.show(Instant::now());
351            Task::none()
352        }
353        Message::DialogDismissed => {
354            state.alert_dialog.dismiss(Instant::now());
355            Task::none()
356        }
357        Message::DialogConfirmed => {
358            state.alert_dialog.dismiss(Instant::now());
359            state.count += 1;
360            Task::none()
361        }
362        Message::ShowSnackbar => {
363            state.snackbar.show(Instant::now());
364            Task::none()
365        }
366        Message::SnackbarUndo => {
367            state.count -= 1;
368            state.snackbar.dismiss(Instant::now());
369            Task::none()
370        }
371        Message::WindowResized(size) => {
372            state.window_size = size;
373            Task::none()
374        }
375        Message::ThemeChanged(action) => {
376            state.theme_controller.update(
377                action,
378                state.window_size,
379                theme_picker::bottom_margin(state.adaptive_navigation_layout()),
380                Instant::now(),
381            );
382            Task::none()
383        }
384        Message::Frame(now) => {
385            let _ = state.theme_controller.advance(now);
386            let _ = state.navigation.advance(now);
387            let _ = state.segment_state.advance(now);
388            let _ = state.primary_tab_state.advance(now);
389            let _ = state.secondary_tab_state.advance(now);
390            state.progress_animation.advance(now);
391            let _ = state.alert_dialog.advance(now);
392            let _ = state.snackbar.advance(now);
393            let _ = state.date_picker.advance(now);
394            let _ = state.date_range_picker.advance(now);
395            let _ = state.time_picker.advance(now);
396            Task::none()
397        }
398    }
399}

Trait Implementations§

Source§

impl<T> Debug for State<T>
where T: Debug,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T> Default for State<T>
where T: Display + Clone,

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<T> !Freeze for State<T>

§

impl<T> !RefUnwindSafe for State<T>

§

impl<T> !Sync for State<T>

§

impl<T> Send for State<T>
where T: Send,

§

impl<T> Unpin for State<T>
where T: Unpin,

§

impl<T> UnsafeUnpin for State<T>

§

impl<T> UnwindSafe for State<T>
where T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<State, Message> IntoBoot<State, Message> for State

Source§

fn into_boot(self) -> (State, Task<Message>)

Turns some type into the initial state of some Application.
Source§

impl<T> MaybeClone for T

Source§

impl<T> MaybeDebug for T

Source§

impl<T> MaybeSend for T
where T: Send,

Source§

impl<T> NoneValue for T
where T: Default,

Source§

type NoneType = T

Source§

fn null_value() -> T

The none-equivalent value.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Upcast<T> for T

Source§

fn upcast(&self) -> Option<&T>

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more