You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Here's a pattern I have seen multiple times in Compose application (and personally use 😄).
Current situation
We have a form with two values, a username and a password.
We have immutable domain objects created using arrow-exact:
@JvmInline value classUsername …
@JvmInline value classPassword …
data classLogInForm(
valusername:Username,
valpassword:Password,
)
However, UI forms have to be mutable. So we need another object to store the values before they are validated:
classMutableLogInForm(
username:String = "",
password:String = "",
) {
constructor(previous:LogIn) :this(previous.username.text, previous.password.text)
// Understanding what mutableStateOf does is not really important here,// except that it's important for Compose to encapsulate and control mutabilityvar username by mutableStateOf(username)
var password by mutableStateOf(password)
funtoImmutable() = either {
LogInForm(
Username.from(username).bind(),
Password.from(password).bind(),
)
}
}
This is not too bad, but there are a few downsides:
Fields are validated in order (we don't use EitherNel)
If validation fails, we don't know which field is the source of the failure
If we want to use EitherNel, we have to split the validation in multiple sub-functions to identify which field is invalid
Proposal
Ideally, I'm imagining some utility class like this:
classMutableLogInForm(
username:String = "",
password:String = "",
) {
constructor(previous:LogIn) :this(previous.username.text, previous.password.text)
val username = validate(username) {
// Full power of the Exact DSL
ensure(Username)
}
val password = validate(password) {
ensure(Password)
}
funtoImmutable() = either {
LogInForm(
username.validate().bind(),
password.validate().bind(),
)
}
}
Usage:
@Composable
funLogInForm() {
val form = remember { MutableLogInForm() }
// 'raw' usageTextField(
label ="Username",
value = form.username.value,
onChange = { form.username.value = it },
failureText = form.username.failure?.toString(),
)
// assuming an appropriate overload which binds everythingPasswordField(
label ="Password",
exactState = form.password,
)
SubmitButton(
onClick = {
val login = form.toImmutable()
logInWith(login)
}
enabled = form.valid,
)
}
If we decide this is out of scope for this project, I'll probably end up implementing it as an optional extra module of Decouple, so I'm interested in your opinions anyway 😇.
The text was updated successfully, but these errors were encountered:
Here's a pattern I have seen multiple times in Compose application (and personally use 😄).
Current situation
We have a form with two values, a username and a password.
We have immutable domain objects created using arrow-exact:
However, UI forms have to be mutable. So we need another object to store the values before they are validated:
This is not too bad, but there are a few downsides:
EitherNel
)EitherNel
, we have to split the validation in multiple sub-functions to identify which field is invalidProposal
Ideally, I'm imagining some utility class like this:
Which allows to declare forms like this:
Usage:
If we decide this is out of scope for this project, I'll probably end up implementing it as an optional extra module of Decouple, so I'm interested in your opinions anyway 😇.
The text was updated successfully, but these errors were encountered: