Iced: Dynamic buttons

Created on 16 Mar 2020  路  8Comments  路  Source: hecrj/iced

Coming from #217 , I want to generate a list of buttons, that will call a Message with different parameters.

Now I'm at a loss of how to handle button::States, that are needed for buttons.

This is my current code, but it doesn't work, because of this error

cannot return value referencing temporary value

temporary value created here
for number in &self.numbers {
    let button = Button::new(&mut button::State::new(), Text::new(format!("Choose: {}", number.number))).on_press(Message::ItemSelected(number.clone()));
    content = content.push(button);
}

I tried making a Vec<button:State>, but that didn't work either, as I wasn't able to add numbers to the self.numbers array of button states.

self.numbers.append(&mut button::State::new());
question

Most helpful comment

@janosimas Glad to know!

I know that writing view code while pleasing the borrow checker can be a bit hard at first. Feel free to join the Zulip chat and ask any questions there! I'm always happy to help.

All 8 comments

You need to store the state of the buttons as part of the state of your application.

The overview in the README and almost all of the examples show how to do this. Specifically, the todos example displays a dynamic list of items including buttons:

https://github.com/hecrj/iced/blob/36e617ae70cc7a86ce998cbd61f6aa702bb42933/examples/todos/src/main.rs#L284-L303

I have exactly the same issue, I want to have a list o files from a folder and be able to click on them.
I could not follow your advice in the last post,
how could I store the state of a dynamically created amouth of buttons?

I feel a little bad by the last message and I removed to not leave a wrongdirection.

I've been able to get a kind of woking version, my aproach was to create a wrapper struct for each button that holds the state.

I cannot post my solution as it's not fully working yet.

@MGlolenstine

It's ok, thanks for sharing your progress @janosimas

Sorry, I missed this.

I could not follow your advice in the last post

Could you elaborate? What are you trying to do? What is the issue specifically?

The idea is that you have a list of button states in your application:

struct MyApp {
    buttons: Vec<button::State>,
}

Then you simply iterate and fold in your view:

let column = self.buttons.iter_mut().fold(Column::new(), |column, button| {
    column.push(Button::new(button, Text::new("A dynamic button"))
});

This is just one way of doing it.

@MGlolenstine Happy to help.

This is my current working version:

pub struct ListItem {
    name: String,
    item_state: button::State,
}

impl ListItem {
    pub fn new(name: String) -> Self {
        Self {
            name,
            item_state: button::State::new(),
        }
    }

    pub fn view(&mut self) -> Element<messages::Messages> {
        Button::new(&mut self.item_state, Text::new(&self.name))
            .on_press(messages::Messages::SomeMessage(self.name.clone()))
            .into()
    }
}

On my List struct, when I call the view method, I iterate in my vector of buttons and push the returned view in my Column.

Now, it's working like a charm.

@MGlolenstine if you have any issue just leave a message :-)

@hecrj Looking at your answer, it looks really simple and I think I missed something about the mutability in my code.
I'm struggling a little to have my head around the paradigm of your library but when I can it works like a charm!

@janosimas Glad to know!

I know that writing view code while pleasing the borrow checker can be a bit hard at first. Feel free to join the Zulip chat and ask any questions there! I'm always happy to help.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Gohla picture Gohla  路  4Comments

sumibi-yakitori picture sumibi-yakitori  路  3Comments

Plecra picture Plecra  路  4Comments

pbspbsingh picture pbspbsingh  路  4Comments

olanod picture olanod  路  4Comments