diff --git a/tutorials/Web/Controlled_Uncontrolled_Inputs/README.md b/tutorials/Web/Controlled_Uncontrolled_Inputs/README.md new file mode 100644 index 0000000000..b01df3af0a --- /dev/null +++ b/tutorials/Web/Controlled_Uncontrolled_Inputs/README.md @@ -0,0 +1,97 @@ +# Controlled and Uncontrolled inputs + +Input components in Compose for Web have two modes: Controlled and Uncontrolled. + +### Controlled vs Uncontrolled behaviour + +Let's create two inputs using different modes and compare them: + +``` kotlin + +// Uncontrolled +Input(type = InputType.Text) { + defaultValue("Initial Value") // optional + onInput { event -> println(event.value) } +} + +// Controlled +Input(type = InputType.Text) { + value("Some value") // calling value(...) is necessary to make input "Controlled" + onInput { event -> println(event.value) } +} +``` + +If you try running these snippets you'll see following behaviour: + +- Uncontrolled text input will show "Initial value". Typing will make corresponding changes to the input's state. +- Controlled text input will show "Some value". But typing will not cause any changes. +- Both inputs will receive an `event` in `onInput { }` handler + +In the example above, we set hardcoded `value` - `value("Some value")`. Therefore, typing does nothing. +Under the hood, controlled input "restores" its state according to last known `value`. + + +### Using MutableState with Controlled Input + +To make Controlled Input more useful we can use `MutableState<*>` to keep input's value: + +``` kotlin +val inputState = remember { mutableStateOf("Some Text") } + +Input(type = InputType.Text) { + value(inputState.value) + onInput { event -> println(event.value) } +} +``` + +We can see that, `inputState` never mutates. If we run such an example as is, we'll see the same behaviour +as when `value(...)` was hardcoded. But if we had some code that updates `inputState`, then Input would recompose and new value would be shown. + +In most cases, `inputState` needs to be changed in `onInput` event handler: +``` kotlin +val inputState = remember { mutableStateOf("Some Text") } + +Input(type = InputType.Text) { + value(inputState.value) + onInput { event -> inputState.value = event.value } +} +``` + +## Conclusion + +Uncontrolled input changes its content independently +while Controlled input's content can be changed only by external state (such as MutableState). + +#### In most cases Controlled input is the default choice. + + +## Convenient controlled inputs + +Here is a list of Composable functions which represent controlled inputs of different types: + +- CheckboxInput +- DateInput +- DateTimeLocalInput +- EmailInput +- FileInput +- MonthInput +- NumberInput +- PasswordInput +- RadioInput +- RangeInput +- SearchInput +- TelInput +- TextInput +- TimeInput +- UrlInput +- WeekInput + +#### Example: + +``` kotlin +val inputState = remember { mutableStateOf("Some Text") } + +TextInput(value = inputState.value) { + onInput { event -> inputState.value = event.value } +} +``` diff --git a/tutorials/Web/README.md b/tutorials/Web/README.md index 0e3274711a..1fe2e38aa3 100644 --- a/tutorials/Web/README.md +++ b/tutorials/Web/README.md @@ -12,6 +12,8 @@ Compose for Web provides multiple ways of declaring user interfaces in Kotlin co [Handing Events](Events_Handling/README.md) - a short overview of Events handling with compose web +[Controlled and Uncontrolled inputs](Controlled_Uncontrolled_Inputs/README.md) - overview of Controlled and Uncontrolled inputs + [Style DSL](Style_Dsl/README.md) - about styling the composable components in web [Using test-utils](Using_Test_Utils/README.md) - about unit testing for @Composable components based on HTML DOM