Skip to content

Commit

Permalink
fix: TextField value handling (#210)
Browse files Browse the repository at this point in the history
Co-authored-by: Michael Liendo <[email protected]>
  • Loading branch information
EstebanBorai and Michael-Liendo authored Jul 20, 2024
1 parent 3feace8 commit fe1d997
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 44 deletions.
2 changes: 1 addition & 1 deletion Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ e2e_tests *args='':

# Runs formatting tool against Leptos source
web-fmt:
leptosfmt ./crates/web/src/*.rs
leptosfmt ./crates/web/src/**/*.rs

# Runs Web UI for Development
web-dev:
Expand Down
2 changes: 1 addition & 1 deletion crates/web/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ path = "src/bin/main.rs"

[dependencies]
leptos = { workspace = true, features = ["csr"] }
leptos_meta = { workspace = true }
leptos_meta = { workspace = true, features = ["csr"] }
leptos_router = { workspace = true, features = ["csr"] }

# Local Dependencies
Expand Down
2 changes: 1 addition & 1 deletion crates/web/src/components/button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub fn Button(
});

view! {
<button id={id} class={class_names} disabled=move || disabled.get()>
<button id=id class=class_names disabled=move || disabled.get()>
<MaybeChildren value=children let:children>
{children()}
</MaybeChildren>
Expand Down
38 changes: 28 additions & 10 deletions crates/web/src/components/text_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use core::fmt;
use std::{collections::HashSet, fmt::Debug};

use leptos::{
component, create_memo, event_target_value, view, Callable, Callback, IntoView, MaybeProp,
SignalGet, TextProp,
component, create_memo, event_target_value, view, IntoView, MaybeProp, RwSignal, SignalGet,
SignalSet, TextProp,
};

#[derive(Clone, Debug, Default)]
Expand Down Expand Up @@ -32,14 +32,13 @@ impl fmt::Display for TextFieldType {

#[component]
pub fn TextField(
#[prop(into)] value: RwSignal<String>,
#[prop(optional, into)] name: TextProp,
#[prop(optional, into)] id: TextProp,
#[prop(optional, into)] id: MaybeProp<TextProp>,
#[prop(optional, into)] placeholder: TextProp,
#[prop(optional, into)] value: TextProp,
#[prop(optional, into)] label: TextProp,
#[prop(optional, into)] class: TextProp,
#[prop(optional, into)] variant: MaybeProp<TextFieldVariant>,
#[prop(optional, into)] on_input: MaybeProp<Callback<String>>,
#[prop(optional, into)] r#type: TextFieldType,
#[prop(optional, into)] disabled: MaybeProp<bool>,
#[prop(optional, into)] full_width: MaybeProp<bool>,
Expand All @@ -66,7 +65,6 @@ pub fn TextField(
}

// Default Classes

if let Some(is_full_width) = full_width.get() {
if is_full_width {
classes.insert("w-full");
Expand All @@ -83,10 +81,30 @@ pub fn TextField(
classes.into_iter().collect::<Vec<&str>>().join(" ")
});

let handle_change = move |ev| {
value.set(event_target_value(&ev));
};

let handle_input = move |ev| {
value.set(event_target_value(&ev));
};

view! {
<div>
<label class="block mb-2 text-sm font-medium text-purple-500" for=id.clone()>{label}</label>
<input type=format!("{}", r#type) name=name value=value id=id placeholder=placeholder class=class_names disabled=disabled on:change=move |ev| {on_input.get().unwrap().call(event_target_value(&ev))} />
</div>
<div>
<label class="block mb-2 text-sm font-medium text-purple-500" for=id.clone()>
{label}
</label>
<input
type=format!("{}", r#type)
name=name
value=value
id=id
placeholder=placeholder
class=class_names
disabled=disabled
on:change=handle_change
on:input=handle_input
/>
</div>
}
}
19 changes: 10 additions & 9 deletions crates/web/src/views/home.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
use crate::components::text_field::{TextField, TextFieldType};
use leptos::{component, leptos_dom::logging, view, IntoView};
use leptos::{component, view, IntoView};

use crate::components::button::{Button, ButtonVariant};

#[component]
pub fn Home() -> impl IntoView {
view! {
<section class="flex flex-col justify-center items-center">
<img src="/assets/img/townhall.png" alt="TownHall AI Generated" height="500" width="500" />
<img
src="/assets/img/townhall.png"
alt="TownHall AI Generated"
height="500"
width="500"
/>
<h1>{"AI Generated Picture of a TownHall"}</h1>
<Button variant={ButtonVariant::Text}>{"Text"}</Button>
<Button variant={ButtonVariant::Contained}>{"Contained"}</Button>
<Button variant={ButtonVariant::Outlined}>{"Outlined"}</Button>
<TextField r#type=TextFieldType::Text placeholder="Simple" />
<TextField placeholder="Label" label="Input Label" id="label" on_input=|val: String| logging::console_log(&val) />
<TextField placeholder="Disabled" disabled={true}/>
<Button variant=ButtonVariant::Text>{"Text"}</Button>
<Button variant=ButtonVariant::Contained>{"Contained"}</Button>
<Button variant=ButtonVariant::Outlined>{"Outlined"}</Button>
</section>
}
}
58 changes: 39 additions & 19 deletions crates/web/src/views/login.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use leptos::{component, create_action, create_signal, view, IntoView, Show, SignalGet, SignalSet};
use leptos::{
component, create_action, create_rw_signal, create_signal, view, IntoView, Show, SignalGet,
SignalGetUntracked, SignalSet,
};

use townhall_client::Client;

Expand All @@ -7,12 +10,14 @@ use crate::components::text_field::{TextField, TextFieldType};
#[component]
pub fn Login() -> impl IntoView {
let (error_getter, error_setter) = create_signal::<Option<String>>(None);
let email_value = create_rw_signal(String::default());
let password_value = create_rw_signal(String::default());

let submit = create_action(move |_| async move {
let handle_submit = create_action(move |_| async move {
let client = Client::new();
let res = client
.auth
.token_create("[email protected]".into(), "12345".into())
.token_create(email_value.get_untracked(), password_value.get_untracked())
.await;

if let Some(ref error) = res.error {
Expand All @@ -21,24 +26,39 @@ pub fn Login() -> impl IntoView {
});

view! {
<div class="min-h-screen relative flex justify-center items-center bg-no-repeat bg-cover bg-slate-800 bg-[url('https://images.unsplash.com/photo-1580192985016-7e15ef081dd8?q=80&w=1961&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D')]">
<div class="absolute bg-black rounded-[50%] w-full h-full blur-[23rem]"></div>
<div class="flex justify-center items-center z-20">
<div class="w-full">
<h1 class="text-6xl text-center font-bold text-white mb-16">TownHall</h1>
<form class="w-96">
<TextField class="w-full" name="email" placeholder="Email" />
<TextField class="w-full" name="password" r#type=TextFieldType::Password placeholder="Password" />
<button type="button" on:click={move |_| submit.dispatch(())}>Login</button>
<Show when=move ||error_getter.get().is_some()>
<div class="bg-rose-600 text-white p-2 rounded-md">
{error_getter.get().unwrap()}
<div class="min-h-screen relative flex justify-center items-center bg-no-repeat bg-cover bg-slate-800 bg-[url('https://images.unsplash.com/photo-1580192985016-7e15ef081dd8?q=80&w=1961&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D')]">
<div class="absolute bg-black rounded-[50%] w-full h-full blur-[23rem]"></div>
<div class="flex justify-center items-center z-20">
<div class="w-full">
<h1 class="text-6xl text-center font-bold text-white mb-16">TownHall</h1>
<form class="w-96" on:submit=move |_| handle_submit.dispatch(())>
<TextField
class="w-full"
name="email"
placeholder="Email"
value=email_value
/>
<TextField
class="w-full"
name="password"
r#type=TextFieldType::Password
placeholder="Password"
value=password_value
/>
<button type="submit">Login</button>
<Show when=move || error_getter.get().is_some()>
<div class="bg-rose-600 text-white p-2 rounded-md">
{error_getter.get().unwrap()}
</div>
</Show>
</form>
<div class="text-center w-full text-white mt-3">
{"Don't have an account? "} <a class="underline" href="/signup">
Sign up!
</a>
</div>
</Show>
</form>
<div class="text-center w-full text-white mt-3">{"Don't have an account? "}<a class="underline" href="/signup">Sign up!</a></div>
</div>
</div>
</div>
</div>
}
}
8 changes: 5 additions & 3 deletions crates/web/tests/components/text_field.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use leptos::{mount_to, view};
use leptos::{create_rw_signal, mount_to, view};

use wasm_bindgen::JsCast;
use wasm_bindgen_test::*;
Expand All @@ -12,10 +12,11 @@ fn default_text_field_class_names_integrity() {
let document = leptos::document();
let test_wrapper = document.create_element("div").unwrap();
let _ = document.body().unwrap().append_child(&test_wrapper);
let value = create_rw_signal(String::new());

mount_to(
test_wrapper.clone().unchecked_into(),
|| view! { <TextField id="text-field" /> },
move || view! { <TextField id="text-field" value /> },
);

let text_field_el = test_wrapper
Expand Down Expand Up @@ -49,10 +50,11 @@ fn default_text_field_custom_class_names_integrity() {
let document = leptos::document();
let test_wrapper = document.create_element("div").unwrap();
let _ = document.body().unwrap().append_child(&test_wrapper);
let value = create_rw_signal(String::new());

mount_to(
test_wrapper.clone().unchecked_into(),
|| view! { <TextField class="w-full" id="text-field" /> },
move || view! { <TextField class="w-full" id="text-field" value /> },
);

let text_field_el = test_wrapper
Expand Down

0 comments on commit fe1d997

Please sign in to comment.