I am trying to show some rows from a table in a Postgres database. I am using SQLX alongside Iced for getting the data.
I am doing something wrong, since I get an empty window. The compiler isn’t complaining. But I don’t get the result I am looking for.
The result I want is to show muliple rows in a column![] widget.
Where am I going wrong. Any help, would be greatly appreciated.
I’ve included the parts of the code that should be relevant, but the whole main.rs is here.
This is the App’s State
#[derive(Debug, Clone, sqlx::FromRow)]
pub struct User {
user_id: uuid::Uuid,
first_name: String,
last_name: String,
email_address: String,
telephone_number: String,
}
// I have some methods on it to create a new User
#[derive(Debug, Clone)]
pub struct ExampleApp {
pgpool: Option<Arc<PgPool>>,
user: User,
pub all_users: Option<Vec<User>>,
}
I have two messages ListAllUsers
and ListAllUsersResult<>
#[derive(Debug, Clone)]
enum Message {
// ...
ListAllUsers,
ListAllUsersResult(Result<Vec<User>, Error>),
}
Inside the fn update
I handle both as follows:
fn update(&mut self, message: Message) -> Task<Message> {
match message {
// ..
Message::ListAllUsers => {
println!("Request ListAllUsers");
Task::perform(
// We need to first get a reference to the T inside the
// Option, and then unwrap it. We use the Arc::clone then
// to create a new reference to pgpool
get_all_users(Arc::clone(self.pgpool.as_ref().unwrap())),
Message::ListAllUsersResult,
)
}
Message::ListAllUsersResult(result) => {
if let Ok(result) = result {
self.all_users = Some(result);
} else {
println!("We couldn't process the result of the Vec<User> ");
}
Task::none()
}
// ...
}
And finally in the fn view
I try I first create a Vec,
so I can use Column::from_vec to construct a column with the rows
fn view(&self) -> Element<Message> {
// There is a button in my code to call the Message::ListAllUsers
// ..
button("Get All Users").on_press(Message::ListAllUsers),
// ...
// We start with an empty vector of Type Element, which is
// the lowest form of a widget, we should be able to push
// widget::row's into it.
let mut all_users_vec: Vec<Element<Message>> = Vec::new();
if self.all_users.is_some() {
for user in self.all_users.as_ref().unwrap().iter() {
all_users_vec.push(
row![
text(&user.first_name),
text(&user.last_name),
text(&user.telephone_number),
text(&user.email_address)
]
.into(),
);
}
}
// We now need to publish it.
// then we can use the from_vec function on the column of rows
// to build an iced element to show on the screen
let all_users_component = Column::from_vec(all_users_vec);
column![form, all_users_component].into()
}
This the async function for getting the rows
This should work. So I do get the correct data here.
async fn get_all_users(pgpool: Arc<PgPool>) -> Result<Vec<User>, Error> {
let mut users: Vec<User> = Vec::new();
let mut incoming = sqlx::query_as::<_, User>(
r#"
SELECT user_id, first_name, last_name, telephone_number, email_address FROM "user"
"#,
)
.fetch(&*pgpool);
while let Ok(user) = incoming.try_next().await {
if let Some(user) = user {
users.push(user);
println!("The updated users get_all_users {:?}", &users);
}
}
Ok(users)
}
Help would be greatly appreciated. I am learning Iced to build something cool, but this is a hurdle for the time being.
Thanks in advance,
Alex