naingaungluu / form-conductor Goto Github PK
View Code? Open in Web Editor NEWA declarative form validation for Jetpack Compose
Home Page: https://formconductor.naingaungluu.me
License: MIT License
A declarative form validation for Jetpack Compose
Home Page: https://formconductor.naingaungluu.me
License: MIT License
We'll need to support evaluation of whether a field should be Mandatory
or Optional
at runtime based on the current form state.
ValidationRule
with access to current form state at the time of validation.Rule
implementationFeature requested by Issue #34
if we have not one validator and for every validator toast different message ,how can i achieve this
import com.boe.itc.b4client.utlis.Required
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import me.naingaungluu.formconductor.annotations.Form
@Form
@Serializable
data class User(
@SerialName("userId")
@Required("User ID is required")
val userName: String = "",
@SerialName("password")
@Required("Password is required")
val password: String = ""
)
Use kotlinx-serialization will report errors
java.lang.IllegalArgumentException: Form data class 'User' needs to have a default constructor parameters.
Following parameters need to have a default value in the constructor:
[seen1, userName, password, serializationConstructorMarker]
Suppose the user selects US citizen: yes, then I want to mandatory some fields; how can I do this with the library?
I was wondering how to get the data out of the form and into somewhere an onClick
handler can access it? I am getting the usual error @Composable invocations can only happen from the context of an @Composable function
.
I assume calling a onClick handler with the form data is a popular option so it may be good to add to the sample.
This may be really obvious, I am new to Jetpack compose ๐
I'm a beginner in android compose. I don't know what went wrong in my code. The button won't enabled during UI test but working during manual testing.
rule.onNode(signInButton).assertIsNotEnabled()
rule.onNode(emailField).assertIsNotFocused()
rule.onNode(emailField).performClick()
rule.onNode(emailField).performTextInput("[email protected]")
rule.onNode(emailField).performImeAction()
rule.onNode(signInButton).assertIsNotEnabled()
rule.onNode(passwordField).assertIsFocused()
rule.onNode(passwordField).performTextInput("password")
rule.onNode(passwordField).performImeAction()
rule.onNode(signInButton).assertIsEnabled() // Failed to assert because the button is disabled
Please advise. Thank you
Edit: I think i know the problem. Compose isn't recompose yet during check assertIsEnabled. But still didn't understand how to fix it
I have my custom text field input, like below:
`form(RegisterRequestDto::class) {
Column(
modifier = Modifier
.fillMaxWidth()
.constrainAs(contentColumn) {
top.linkTo(parent.top)
bottom.linkTo(button.top, margin = (200).dp)
start.linkTo(parent.start)
end.linkTo(parent.end)
}
) {
field(fieldClass = RegisterRequestDto::name) {
InputTextField(
labelValue = stringResource(id = R.string.text_name),
onTextChanged = {
registerViewModel.onTriggerEvent(RegisterEvent.NameChanged(it))
}
)
}
LargeSpacer()
field(fieldClass = RegisterRequestDto::email) {
InputTextField(
labelValue = stringResource(id = R.string.text_email),
onTextChanged = {
registerViewModel.onTriggerEvent(RegisterEvent.EmailChanged(it))
}
)
}
LargeSpacer()
field(fieldClass = RegisterRequestDto::password) {
PasswordTextField(
labelValue = stringResource(id = R.string.text_password),
onTextChanged = {
registerViewModel.onTriggerEvent(RegisterEvent.PasswordChanged(it))
}
)
}
LargeSpacer()
field(fieldClass = RegisterRequestDto::confirmPassword) {
PasswordTextField(
labelValue = stringResource(id = R.string.text_confirm_password),
onTextChanged = {
registerViewModel.onTriggerEvent(
RegisterEvent.ConfirmPasswordChanged(
it
)
)
}
)
}
}
ButtonView(
value = stringResource(id = R.string.text_register),
onButtonClicked = {
registerViewModel.onTriggerEvent(RegisterEvent.DoRegister)
navigator.openLogin()
},
isEnabled = this.formState.value is FormResult.Success,
modifier = Modifier
.constrainAs(button) {
bottom.linkTo(parent.bottom)
start.linkTo(parent.start)
end.linkTo(parent.end)
}
)
}
}`
Is i'm doing it correctly? Because the validation is not working
Form
@Form
@JsonClass(generateAdapter = true)
data class User(
@Json(name = "userId")
@MinLength(1)
val userName: String = "",
@Json(name = "password")
@MinLength(1)
val password: String = ""
)
Compose
Column {
form(User::class) {
field(User::userName) {
TextField(
value = state.value?.value.orEmpty(),
onValueChange = this::setField
)
}
field(User::password) {
TextField(
value = state.value?.value.orEmpty(),
onValueChange = this::setField
)
}
val formResult = this.formState.value
Button(
enabled = formResult is FormResult.Success,
onClick = {
}
) {
Text(text = "Login")
}
}
}
When I type nothing, the default button state is available
Let's say you have this simple form
@Form
data class SignUpForm(
@Optional
@MaxLength(150)
val address: String? = null
)
In the UI using effect you update the form by submitting it
form(SignUpForm::class) {
// formData is SignUpForm == true
// formData = SignUpForm()
LaunchedEffect(formData) { submit(formData) }
}
This causing an error like this
FATAL EXCEPTION: main
Process: com.bangkit.coffee, PID: 26216
java.lang.NullPointerException: null cannot be cast to non-null type kotlin.Any
at me.naingaungluu.formconductor.FormImpl.submit(FormImpl.kt:183)
at me.naingaungluu.formconductor.composeui.scope.FormScopeImpl.submit(FormScopeImpl.kt:29)
...
But if you change the default into empty string instead null, the problem is gone
val address: String? = ""
The problem exists if you update the form via submit()
within the field formbuilderscope when adding TextField or Row/Column etc. my IDE shows me the following error: @composable invocations can only happen from the context of a @composable function
We'll need to support priority values in form field annotations to specify the order in which they are validated
@Form
data class FormData(
@Priority(2)
val emailAddress: String,
@Priority(1)
val name: String,
@Priority(3)
val countryCode: String,
@Priority(4)
val mobileNumber: String
)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.