Skip to content

Instantly share code, notes, and snippets.

@rebo
Last active July 23, 2020 11:24
Show Gist options
  • Save rebo/009079899e3b5521b6d196b95342de7e to your computer and use it in GitHub Desktop.
Save rebo/009079899e3b5521b6d196b95342de7e to your computer and use it in GitHub Desktop.
//
// ...
// Regular Seed app/init/model/msg stuff here..
// ...
//
#[wasm_bindgen(start)]
pub fn start() {
let app = App::start("app", init, update, view);
my_app().set(Some(app));
}
#[atom]
fn my_app() -> Atom<Option<App<Msg,Model,Node<Msg>>>>{
None
}
#[derive(Debug, Default, Validate, Deserialize,Clone)]
struct SignupData {
#[validate(email)]
mail: String,
#[validate(url)]
site: String,
#[validate(length(min = 1), custom = "validate_unique_username")]
#[serde(rename = "firstName")]
first_name: String,
#[validate(range(min = 18, max = 45))]
age: u32,
}
// User struct for querying server
#[derive(Deserialize, Debug,Clone)]
pub struct User {
id: u32,
email: String,
username:String,
phone:String,
}
fn validate_unique_username(username: &str) -> Result<(), ValidationError> {
if username == "xXxShad0wxXx" {
// the value of the username will automatically be added later
return Err(ValidationError::new("terrible_username"));
}
Ok(())
}
#[atom]
fn signup_data() -> Atom<SignupData> {
SignupData::default()
}
#[reaction]
fn client_validation() -> Reaction<Result<(), ValidationErrors>> {
signup_data().observe().validate()
}
#[atom]
fn server_validation_response() -> Atom<Result<Result<(), ValidationErrors>, String >>{
Err("Not Checked Yet".to_string())
}
#[reaction]
fn server_validation() -> Reaction<()> { // we dont care about the return value here
if let Ok(_) = client_validation().observe() {
let signup_data = signup_data().get();
// The below does a fetch request for the username from Json Placeholder mock site
// it needs to match the first_name field from the struct for it to pas validation
spawn_local({
async move {
let fetch_url = "https://jsonplaceholder.typicode.com/users/1";
let response = fetch(fetch_url).await.expect("HTTP request failed");
match response.check_status(){
Ok(response) => {
let user = response
.json::<User>()
.await
.expect("deserialization failed");
log!(user.username);
if user.username == signup_data.first_name {
server_validation_response().update(|r|
*r = Ok(Ok(()))
)
} else {
server_validation_response().update(|r|
*r = Err(format!("Usernames dont match!! it should be {}", user.username ))
)
}
},
Err(_error) => {
server_validation_response().update(|r| *r = Err("server connection error".to_string() ))
}
}
my_app().get().unwrap().update_with_option(None);
}
});
}
}
#[reaction]
fn form_widget() -> Reaction<Node<Msg>> {
let form_data = signup_data().observe();
let client_errors = client_validation().observe();
let server_errors = server_validation_response().observe();
server_validation().observe();
div![
form![
s().style_child("input").b_width(px(1)).b_color("gray").b_style_solid().display_block(),
label!["Mail"],
input![attrs![At::Value => form_data.mail ], signup_data().on_input(|data,inp| data.mail = inp)],
label!["Site"],
input![attrs![At::Value => form_data.site ], signup_data().on_input(|data,inp| data.site = inp)],
label!["First Name"],
input![attrs![At::Value => form_data.first_name ], signup_data().on_input(|data,inp| data.first_name = inp)],
label!["Age"],
input![attrs![At::Value => form_data.age ], signup_data().on_input(|data,inp| data.age = inp.parse::<u32>().unwrap())],
],
h1!["Client Errors: "],
match client_errors {
Ok(_) => span!["None"],
Err(err) => pre![format!("{:#?}",err)],
},
h1!["Server Errors: "],
match server_errors {
Ok(Ok(_)) => span!["None"],
Ok(Err(err)) => pre![format!("{:#?}",err)],
Err(err) => pre![err],
}
]
}
#[topo::nested] // Needed for Seed Hooks
pub fn view(_model: &Model) -> Node<Msg> {
form_widget().get()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment