---
title: "TextFieldState"
description: "The editable text state of a text field, including both the [text] itself and position of the
cursor or selection.

To change the text field contents programmatically, call [edit], [setTextAndSelectAll],
[setTextAndPlaceCursorAtEnd], or [clearText]. Individual parts of the state like [text],
[selection], or [composition] can be read from any snapshot restart scope like Composable
functions. To observe these members from outside a restart scope, use `snapshotFlow {
textFieldState.text }` or `snapshotFlow { textFieldState.selection }`.

When instantiating this class from a composable, use [rememberTextFieldState] to automatically
save and restore the field state. For more advanced use cases, pass [TextFieldState.Saver] to
[rememberSaveable]."
type: "class"
---

<div class='type'>Class</div>


<a id='references'></a>

<div class='sourceset sourceset-common'>Common</div>


```kotlin
class TextFieldState
internal constructor(
    initialText: String,
    initialSelection: TextRange,
    initialTextUndoManager: TextUndoManager,
)
```


The editable text state of a text field, including both the `text` itself and position of the
cursor or selection.

To change the text field contents programmatically, call `edit`, `setTextAndSelectAll`,
`setTextAndPlaceCursorAtEnd`, or `clearText`. Individual parts of the state like `text`,
`selection`, or `composition` can be read from any snapshot restart scope like Composable
functions. To observe these members from outside a restart scope, use `snapshotFlow {
textFieldState.text }` or `snapshotFlow { textFieldState.selection }`.

When instantiating this class from a composable, use `rememberTextFieldState` to automatically
save and restore the field state. For more advanced use cases, pass `TextFieldState.Saver` to
`rememberSaveable`.


## Secondary Constructors

```kotlin
@RememberInComposition
constructor(
    initialText: String = "",
    initialSelection: TextRange = TextRange(initialText.length),
) : this(initialText, initialSelection, TextUndoManager())
```

## Properties

<div class='sourceset sourceset-common'>Common</div>


```kotlin
val text: CharSequence
```


The current text content. This value will automatically update when the user enters text or
otherwise changes the text field contents. To change it programmatically, call `edit`.

To observe changes to this property outside a restartable function, use `snapshotFlow { text
}`.



<div class='sourceset sourceset-common'>Common</div>


```kotlin
val selection: TextRange
```


The current selection range. If the selection is collapsed, it represents cursor location.
This value will automatically update when the user enters text or otherwise changes the text
field selection range. To change it programmatically, call `edit`.

To observe changes to this property outside a restartable function, use `snapshotFlow {
selection }`.



<div class='sourceset sourceset-common'>Common</div>


```kotlin
val composition: TextRange?
```


The current composing range dictated by the IME. If null, there is no composing region.

To observe changes to this property outside a restartable function, use `snapshotFlow {
composition }`.



<div class='sourceset sourceset-common'>Common</div>


```kotlin
@ExperimentalFoundationApi val undoState: UndoState
```


Undo history controller for this TextFieldState.



## Functions

```kotlin
inline fun edit(block: TextFieldBuffer.() -> Unit)
```


Runs `block` with a mutable version of the current state. The block can make changes to the
text and cursor/selection. See the documentation on `TextFieldBuffer` for a more detailed
description of the available operations.

Make sure that you do not make concurrent calls to this function or call it again inside
`block`'s scope. Doing either of these actions will result in triggering an
`IllegalStateException`.



## Code Examples

### BasicTextFieldStateCompleteSample
```kotlin
fun BasicTextFieldStateCompleteSample() {
    class SearchViewModel(val searchFieldState: TextFieldState = TextFieldState()) {
        private val queryValidationRegex = """\w+""".toRegex()
        // Use derived state to avoid recomposing every time the text changes, and only recompose
        // when the input becomes valid or invalid.
        val isQueryValid by derivedStateOf {
            // This lambda will be re-executed every time inputState.text changes.
            searchFieldState.text.matches(queryValidationRegex)
        }
        var searchResults: List<String> by mutableStateOf(emptyList())
            private set
        /** Called while the view model is active, e.g. from a LaunchedEffect. */
        suspend fun run() {
            snapshotFlow { searchFieldState.text }
                .collectLatest { queryText ->
                    // Start a new search every time the user types something valid. If the previous
                    // search is still being processed when the text is changed, it will be
                    // cancelled
                    // and this code will run again with the latest query text.
                    if (isQueryValid) {
                        searchResults = performSearch(query = queryText)
                    }
                }
        }
        fun clearQuery() {
            searchFieldState.setTextAndPlaceCursorAtEnd("")
        }
        private suspend fun performSearch(query: CharSequence): List<String> {
            TODO()
        }
    }
    @Composable
    fun SearchScreen(viewModel: SearchViewModel) {
        Column {
            Row {
                BasicTextField(viewModel.searchFieldState)
                IconButton(onClick = { viewModel.clearQuery() }) {
                    Icon(Icons.Default.Clear, contentDescription = "clear search query")
                }
            }
            if (!viewModel.isQueryValid) {
                Text("Invalid query", style = TextStyle(color = Color.Red))
            }
            LazyColumn { items(viewModel.searchResults) { TODO() } }
        }
    }
}
```

