build
Basic builder for a Form.
To build a basic non-composite Form (e.x. something like a text entry field), you can simply use the FormScope.currentValue property in scope of the builder and bind that to your UI:
class StringEntry(val fieldLabel: String): Form<String> by (Form.build {
var text by currentValue
Column {
Text(fieldLabel)
BasicTextField(
value = fieldLabel,
onValueChanged = { newText ->
text = newText
}
)
}
})
However, one of the main advantages of Forms over raw composable functions is the ability to embed sub-forms when building the entry form for a larger type without much ceremony.
Like most things in Jetpack Compose, Form works with immutable data types. We use the arrow-optics ksp plugin and the @Optics
annotation to automatically generate Lenses that let us easily reference a "part" of our form. For example, given the following:
@Optics
data class User(
val firstName: String,
val lastName: String,
val birthday: LocalDate
) {
companion object
}
we can do the following to build a user entry form:
class UserEntryForm(): Form<User> by (Form.build {
StringEntry("First name:")
.bind(User.firstName)
StringEntry("Last name:")
.bind(User.lastName)
LocalDateEntry()
.bind(User.birthday)
})
which can then be used like any other composable in the rest of your application with .contents()
.