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 207-210)
197    fn default() -> Self {
198        Self {
199            navigation: navigation::NavigationState::new(ShowcasePage::Inputs),
200            window_size: Size::new(1080.0, 980.0),
201            count: 0,
202            note: String::new(),
203            editor_content: material::widget::text_editor::Content::with_text(
204                "Material 3 multi-line text editor",
205            ),
206            select_choice: Some("Assist"),
207            combobox_options: material::widget::combobox::State::with_selection(
208                vec!["Assist", "Suggestion", "Filter"],
209                Some(&"Suggestion"),
210            ),
211            combobox_choice: Some("Suggestion"),
212            combobox_input: String::new(),
213            search_query: String::new(),
214            date_picker: material::widget::picker::DatePickerState::new(
215                material::widget::picker::Date::new(2026, 7, 4),
216            ),
217            date_range_picker: material::widget::picker::DateRangePickerState::new(
218                material::widget::picker::Date::new(2026, 7, 4),
219                material::widget::picker::Date::new(2026, 7, 10),
220            ),
221            time_picker: material::widget::picker::TimePickerState::new(14, 30, false),
222            progress: 42.0,
223            enabled: true,
224            radio_choice: Some(RadioChoice::Standard),
225            segment_choice: SegmentChoice::List,
226            segment_state: material::widget::segmented_button::State::new(
227                SegmentChoice::List.index(),
228            ),
229            primary_tab: TabChoice::Inputs,
230            primary_tab_state: material::widget::tabs::State::new(TabChoice::Inputs.index()),
231            secondary_tab: TabChoice::Controls,
232            secondary_tab_state: material::widget::tabs::State::new(TabChoice::Controls.index()),
233            log_viewer: material::widget::log_viewer::State::new(),
234            log_entries: sample_log_entries(),
235            progress_animation: material::widget::progress_bar::IndeterminateState::new(
236                Instant::now(),
237            ),
238            alert_dialog: material::widget::dialog::Transition::default(),
239            snackbar: material::widget::snackbar::Transition::default(),
240            theme_controller: theme_picker::ThemeController::default(),
241        }
242    }
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 298)
259fn update(state: &mut Showcase, message: Message) -> Task<Message> {
260    match message {
261        #[cfg(any(target_arch = "wasm32", test))]
262        Message::CjkCoreFontFinished => load_cjk_regional_font(),
263        #[cfg(any(target_arch = "wasm32", test))]
264        Message::CjkRegionalFontFinished => Task::none(),
265        Message::Navigate(page) => {
266            state
267                .navigation
268                .select(page, Instant::now(), state.adaptive_navigation_layout());
269            Task::none()
270        }
271        Message::Increment => {
272            state.count += 1;
273            Task::none()
274        }
275        Message::Decrement => {
276            state.count -= 1;
277            Task::none()
278        }
279        Message::TextChanged(note) => {
280            state.note = note;
281            Task::none()
282        }
283        Message::EditorAction(action) => {
284            state.editor_content.perform(action);
285            Task::none()
286        }
287        Message::SelectChanged(choice) => {
288            state.select_choice = Some(choice);
289            Task::none()
290        }
291        Message::ComboboxSelected(choice) => {
292            state.combobox_choice = Some(choice);
293            state.combobox_input.clear();
294            state.combobox_options.set_selection(Some(&choice));
295            Task::none()
296        }
297        Message::ComboboxInputChanged(input) => {
298            state.combobox_options.set_input(input.clone());
299            state.combobox_input = input;
300            state.combobox_choice = None;
301            Task::none()
302        }
303        Message::SearchChanged(query) => {
304            state.search_query = query;
305            Task::none()
306        }
307        Message::DatePickerChanged(action) => state.date_picker.update_and_scroll(action),
308        Message::DateRangePickerChanged(action) => {
309            state.date_range_picker.update_and_scroll(action)
310        }
311        Message::TimePickerChanged(action) => {
312            state.time_picker.update(action);
313            Task::none()
314        }
315        Message::SliderChanged(progress) => {
316            state.progress = progress;
317            Task::none()
318        }
319        Message::EnabledChanged(enabled) => {
320            state.enabled = enabled;
321            Task::none()
322        }
323        Message::ChoiceSelected(choice) => {
324            state.radio_choice = Some(choice);
325            Task::none()
326        }
327        Message::SegmentSelected(choice) => {
328            state.segment_choice = choice;
329            state.segment_state.select(choice.index(), Instant::now());
330            Task::none()
331        }
332        Message::PrimaryTabSelected(choice) => {
333            state.primary_tab = choice;
334            state.primary_tab_state.select(
335                choice.index(),
336                Instant::now(),
337                material::widget::tabs::Variant::Primary,
338            );
339            Task::none()
340        }
341        Message::SecondaryTabSelected(choice) => {
342            state.secondary_tab = choice;
343            state.secondary_tab_state.select(
344                choice.index(),
345                Instant::now(),
346                material::widget::tabs::Variant::Secondary,
347            );
348            Task::none()
349        }
350        Message::LogViewer(action) => state.log_viewer.update(action, &state.log_entries),
351        Message::MenuPressed => {
352            state.navigation.toggle_menu_now();
353            Task::none()
354        }
355        Message::DialogOpened => {
356            state.alert_dialog.show(Instant::now());
357            Task::none()
358        }
359        Message::DialogDismissed => {
360            state.alert_dialog.dismiss(Instant::now());
361            Task::none()
362        }
363        Message::DialogConfirmed => {
364            state.alert_dialog.dismiss(Instant::now());
365            state.count += 1;
366            Task::none()
367        }
368        Message::ShowSnackbar => {
369            state.snackbar.show(Instant::now());
370            Task::none()
371        }
372        Message::SnackbarUndo => {
373            state.count -= 1;
374            state.snackbar.dismiss(Instant::now());
375            Task::none()
376        }
377        Message::WindowResized(size) => {
378            state.window_size = size;
379            Task::none()
380        }
381        Message::ThemeChanged(action) => {
382            state.theme_controller.update(
383                action,
384                state.window_size,
385                theme_picker::bottom_margin(state.adaptive_navigation_layout()),
386                Instant::now(),
387            );
388            Task::none()
389        }
390        Message::Frame(now) => {
391            let _ = state.theme_controller.advance(now);
392            let _ = state.navigation.advance(now);
393            let _ = state.segment_state.advance(now);
394            let _ = state.primary_tab_state.advance(now);
395            let _ = state.secondary_tab_state.advance(now);
396            let _ = state.log_viewer.advance(now);
397            state.progress_animation.advance(now);
398            let _ = state.alert_dialog.advance(now);
399            let _ = state.snackbar.advance(now);
400            let _ = state.date_picker.advance(now);
401            let _ = state.date_range_picker.advance(now);
402            let _ = state.time_picker.advance(now);
403            Task::none()
404        }
405    }
406}
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 294)
259fn update(state: &mut Showcase, message: Message) -> Task<Message> {
260    match message {
261        #[cfg(any(target_arch = "wasm32", test))]
262        Message::CjkCoreFontFinished => load_cjk_regional_font(),
263        #[cfg(any(target_arch = "wasm32", test))]
264        Message::CjkRegionalFontFinished => Task::none(),
265        Message::Navigate(page) => {
266            state
267                .navigation
268                .select(page, Instant::now(), state.adaptive_navigation_layout());
269            Task::none()
270        }
271        Message::Increment => {
272            state.count += 1;
273            Task::none()
274        }
275        Message::Decrement => {
276            state.count -= 1;
277            Task::none()
278        }
279        Message::TextChanged(note) => {
280            state.note = note;
281            Task::none()
282        }
283        Message::EditorAction(action) => {
284            state.editor_content.perform(action);
285            Task::none()
286        }
287        Message::SelectChanged(choice) => {
288            state.select_choice = Some(choice);
289            Task::none()
290        }
291        Message::ComboboxSelected(choice) => {
292            state.combobox_choice = Some(choice);
293            state.combobox_input.clear();
294            state.combobox_options.set_selection(Some(&choice));
295            Task::none()
296        }
297        Message::ComboboxInputChanged(input) => {
298            state.combobox_options.set_input(input.clone());
299            state.combobox_input = input;
300            state.combobox_choice = None;
301            Task::none()
302        }
303        Message::SearchChanged(query) => {
304            state.search_query = query;
305            Task::none()
306        }
307        Message::DatePickerChanged(action) => state.date_picker.update_and_scroll(action),
308        Message::DateRangePickerChanged(action) => {
309            state.date_range_picker.update_and_scroll(action)
310        }
311        Message::TimePickerChanged(action) => {
312            state.time_picker.update(action);
313            Task::none()
314        }
315        Message::SliderChanged(progress) => {
316            state.progress = progress;
317            Task::none()
318        }
319        Message::EnabledChanged(enabled) => {
320            state.enabled = enabled;
321            Task::none()
322        }
323        Message::ChoiceSelected(choice) => {
324            state.radio_choice = Some(choice);
325            Task::none()
326        }
327        Message::SegmentSelected(choice) => {
328            state.segment_choice = choice;
329            state.segment_state.select(choice.index(), Instant::now());
330            Task::none()
331        }
332        Message::PrimaryTabSelected(choice) => {
333            state.primary_tab = choice;
334            state.primary_tab_state.select(
335                choice.index(),
336                Instant::now(),
337                material::widget::tabs::Variant::Primary,
338            );
339            Task::none()
340        }
341        Message::SecondaryTabSelected(choice) => {
342            state.secondary_tab = choice;
343            state.secondary_tab_state.select(
344                choice.index(),
345                Instant::now(),
346                material::widget::tabs::Variant::Secondary,
347            );
348            Task::none()
349        }
350        Message::LogViewer(action) => state.log_viewer.update(action, &state.log_entries),
351        Message::MenuPressed => {
352            state.navigation.toggle_menu_now();
353            Task::none()
354        }
355        Message::DialogOpened => {
356            state.alert_dialog.show(Instant::now());
357            Task::none()
358        }
359        Message::DialogDismissed => {
360            state.alert_dialog.dismiss(Instant::now());
361            Task::none()
362        }
363        Message::DialogConfirmed => {
364            state.alert_dialog.dismiss(Instant::now());
365            state.count += 1;
366            Task::none()
367        }
368        Message::ShowSnackbar => {
369            state.snackbar.show(Instant::now());
370            Task::none()
371        }
372        Message::SnackbarUndo => {
373            state.count -= 1;
374            state.snackbar.dismiss(Instant::now());
375            Task::none()
376        }
377        Message::WindowResized(size) => {
378            state.window_size = size;
379            Task::none()
380        }
381        Message::ThemeChanged(action) => {
382            state.theme_controller.update(
383                action,
384                state.window_size,
385                theme_picker::bottom_margin(state.adaptive_navigation_layout()),
386                Instant::now(),
387            );
388            Task::none()
389        }
390        Message::Frame(now) => {
391            let _ = state.theme_controller.advance(now);
392            let _ = state.navigation.advance(now);
393            let _ = state.segment_state.advance(now);
394            let _ = state.primary_tab_state.advance(now);
395            let _ = state.secondary_tab_state.advance(now);
396            let _ = state.log_viewer.advance(now);
397            state.progress_animation.advance(now);
398            let _ = state.alert_dialog.advance(now);
399            let _ = state.snackbar.advance(now);
400            let _ = state.date_picker.advance(now);
401            let _ = state.date_range_picker.advance(now);
402            let _ = state.time_picker.advance(now);
403            Task::none()
404        }
405    }
406}

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