diff --git a/components-compose/CHANGELOG.md b/components-compose/CHANGELOG.md index 6fc30073..7e0a0839 100644 --- a/components-compose/CHANGELOG.md +++ b/components-compose/CHANGELOG.md @@ -20,6 +20,15 @@ Allowed headings: * `SelectRowView` aligned to top of radio button rather than centered * Dependency updates +* The `initialInputValue` parameter of `TextInputView` and `CurrencyInputView` has been renamed to `value` + +### Added + +* `TextInputView` and `CurrencyInputView` now support `maxChars` + +### Fixed + +* `TextInputView` and `CurrencyInputView` input can now be cleared by setting the `value` parameter ## [0.1.1] - 2024-08-08Z diff --git a/components-compose/src/main/java/uk/gov/hmrc/components/compose/molecule/input/CurrencyInputView.kt b/components-compose/src/main/java/uk/gov/hmrc/components/compose/molecule/input/CurrencyInputView.kt index da8d479c..505d5988 100644 --- a/components-compose/src/main/java/uk/gov/hmrc/components/compose/molecule/input/CurrencyInputView.kt +++ b/components-compose/src/main/java/uk/gov/hmrc/components/compose/molecule/input/CurrencyInputView.kt @@ -28,7 +28,7 @@ import uk.gov.hmrc.components.compose.ui.theme.HmrcTheme @Composable fun CurrencyInputView( modifier: Modifier = Modifier, - initialInputValue: String = "", + value: String? = null, onInputValueChange: ((String) -> Unit)? = null, labelText: String? = null, labelContentDescription: String? = null, @@ -39,6 +39,7 @@ fun CurrencyInputView( errorContentDescription: String? = null, singleLine: Boolean = true, enableDecimal: Boolean = true, + maxChars: Int? = null, ) { // pattern matches a decimal number @@ -54,7 +55,7 @@ fun CurrencyInputView( TextInputView( modifier = modifier, - initialInputValue = initialInputValue, + value = value, onInputValueChange = onInputValueChange, inputFilter = { it: String, localValue: String -> decimalPatternChecker(it, localValue) }, labelText = labelText, @@ -73,7 +74,8 @@ fun CurrencyInputView( singleLine = singleLine, keyboardOptions = KeyboardOptions( keyboardType = if (enableDecimal) KeyboardType.Decimal else KeyboardType.Number - ) + ), + maxChars = maxChars ) } diff --git a/components-compose/src/main/java/uk/gov/hmrc/components/compose/molecule/input/TextInputView.kt b/components-compose/src/main/java/uk/gov/hmrc/components/compose/molecule/input/TextInputView.kt index 56b9c1ac..8246e1ae 100644 --- a/components-compose/src/main/java/uk/gov/hmrc/components/compose/molecule/input/TextInputView.kt +++ b/components-compose/src/main/java/uk/gov/hmrc/components/compose/molecule/input/TextInputView.kt @@ -56,7 +56,7 @@ object TextInputView { @Composable operator fun invoke( modifier: Modifier = Modifier, - initialInputValue: String = "", + value: String? = null, onInputValueChange: ((String) -> Unit)? = null, inputFilter: ((String, String) -> String)? = null, labelText: String? = null, @@ -68,10 +68,13 @@ object TextInputView { errorText: String? = null, errorContentDescription: String? = null, characterCount: Int? = null, + maxChars: Int? = null, singleLine: Boolean = false, keyboardOptions: KeyboardOptions = KeyboardOptions.Default ) { - var localValue: String by rememberSaveable { mutableStateOf(initialInputValue) } + var localValue: String by rememberSaveable { mutableStateOf(value.orEmpty()) } + localValue = value.orEmpty() + var localError: String? by rememberSaveable { mutableStateOf(null) } localError = errorText @@ -142,10 +145,13 @@ object TextInputView { isError = !localError.isNullOrEmpty() || (localValue.length > (characterCount ?: Int.MAX_VALUE)), value = localValue, onInputValueChange = { newValue -> - if (onInputValueChange != null) { onInputValueChange(newValue) } - localValue = if (inputFilter != null && newValue.isNotEmpty()) { - inputFilter(newValue, localValue) - } else newValue + if (maxChars?.let { newValue.length <= it } != false) { + localValue = if (inputFilter != null && newValue.isNotEmpty()) { + val filteredValue = inputFilter(newValue, localValue) + if (onInputValueChange != null) { onInputValueChange(filteredValue) } + filteredValue + } else newValue + } }, prefix = prefix, placeholderText = { placeholderText?.let { Text(text = it) } }, diff --git a/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/presentation/screens/molecules/CurrencyInputViewScreen.kt b/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/presentation/screens/molecules/CurrencyInputViewScreen.kt index 30b26851..914b530d 100644 --- a/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/presentation/screens/molecules/CurrencyInputViewScreen.kt +++ b/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/presentation/screens/molecules/CurrencyInputViewScreen.kt @@ -17,10 +17,15 @@ package uk.gov.hmrc.sample_compose_fragments.presentation.screens.molecules import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel +import uk.gov.hmrc.components.compose.atom.text.BodyText import uk.gov.hmrc.components.compose.molecule.input.CurrencyInputView import uk.gov.hmrc.components.compose.organism.HmrcCardView import uk.gov.hmrc.components.compose.ui.theme.HmrcTheme @@ -37,9 +42,17 @@ fun CurrencyInputViewScreen() { val errorText = stringResource(id = R.string.currency_input_example_error) + var placeholderValue: String by rememberSaveable { mutableStateOf("") } + var example1Value: String by rememberSaveable { mutableStateOf("") } + var example2Value: String by rememberSaveable { mutableStateOf("") } + var example3Value: String by rememberSaveable { mutableStateOf("123.45") } + var example4Value: String by rememberSaveable { mutableStateOf("123.45") } + ScreenScrollViewColumn { PlaceholderSlot { CurrencyInputView( + value = placeholderValue, + onInputValueChange = { placeholderValue = it }, labelText = stringResource(id = R.string.currency_input_placeholder_label), hintText = stringResource(id = R.string.currency_input_placeholder_hint), placeholderText = stringResource(id = R.string.currency_input_placeholder_placeholder), @@ -50,36 +63,50 @@ fun CurrencyInputViewScreen() { ExamplesSlot { HmrcCardView { CurrencyInputView( + value = example1Value, modifier = Modifier.padding( horizontal = HmrcTheme.dimensions.hmrcSpacing16, vertical = HmrcTheme.dimensions.hmrcSpacing24, ), - onInputValueChange = { viewModel.isEmptyValidation(it, errorText, 0) }, + onInputValueChange = { + viewModel.isEmptyValidation(it, errorText, 0) + example1Value = it + }, errorText = viewModel.textInputErrorEmptyValidation.collectAsStateWithLifecycle().value, labelText = stringResource(id = R.string.currency_input_example_1_label), hintText = stringResource(id = R.string.currency_input_example_1_hint), - enableDecimal = true + enableDecimal = true, + maxChars = 4 ) + BodyText(text = example1Value) CurrencyInputView( + value = example2Value, modifier = Modifier.padding( horizontal = HmrcTheme.dimensions.hmrcSpacing16, vertical = HmrcTheme.dimensions.hmrcSpacing24, ), - onInputValueChange = { viewModel.isEmptyValidation(it, errorText, 1) }, + onInputValueChange = { + viewModel.isEmptyValidation(it, errorText, 1) + example2Value = it + }, errorText = viewModel.textInputErrorEmptyValidation1.collectAsStateWithLifecycle().value, labelText = stringResource(id = R.string.currency_input_example_2_label), hintText = stringResource(id = R.string.currency_input_example_2_hint), enableDecimal = false ) + BodyText(text = example2Value) CurrencyInputView( modifier = Modifier.padding( horizontal = HmrcTheme.dimensions.hmrcSpacing16, vertical = HmrcTheme.dimensions.hmrcSpacing24, ), - initialInputValue = stringResource(id = R.string.currency_input_example_3_text), - onInputValueChange = { viewModel.isEmptyValidation(it, errorText, 2) }, + value = example3Value, + onInputValueChange = { + viewModel.isEmptyValidation(it, errorText, 2) + example3Value = it + }, errorText = viewModel.textInputErrorEmptyValidation2.collectAsStateWithLifecycle().value, labelText = stringResource(id = R.string.currency_input_example_3_label), hintText = stringResource(id = R.string.currency_input_example_3_hint), @@ -91,8 +118,11 @@ fun CurrencyInputViewScreen() { horizontal = HmrcTheme.dimensions.hmrcSpacing16, vertical = HmrcTheme.dimensions.hmrcSpacing24, ), - initialInputValue = stringResource(id = R.string.currency_input_example_3_text), - onInputValueChange = { viewModel.isEmptyValidation(it, errorText, 3) }, + value = example4Value, + onInputValueChange = { + viewModel.isEmptyValidation(it, errorText, 3) + example4Value = it + }, errorText = viewModel.textInputErrorEmptyValidation3.collectAsStateWithLifecycle().value, labelText = stringResource(id = R.string.currency_input_example_4_label), hintText = stringResource(id = R.string.currency_input_example_4_hint), diff --git a/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/presentation/screens/molecules/TextInputViewScreen.kt b/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/presentation/screens/molecules/TextInputViewScreen.kt index 6e0f27cd..9dca4e6e 100644 --- a/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/presentation/screens/molecules/TextInputViewScreen.kt +++ b/sample-compose-fragments/src/main/java/uk/gov/hmrc/sample_compose_fragments/presentation/screens/molecules/TextInputViewScreen.kt @@ -17,6 +17,10 @@ package uk.gov.hmrc.sample_compose_fragments.presentation.screens.molecules import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -39,17 +43,26 @@ fun TextInputViewScreen() { val errorTextEx2 = stringResource(id = R.string.text_input_example_2_error) val errorTextEx3 = stringResource(id = R.string.text_input_example_3_error) + var placeholderValue: String by rememberSaveable { mutableStateOf("") } + var example1Value: String by rememberSaveable { mutableStateOf("") } + var example2Value: String by rememberSaveable { mutableStateOf("") } + var example3Value: String by rememberSaveable { mutableStateOf("") } + ScreenScrollViewColumn { val characterCount = 50 PlaceholderSlot { TextInputView( - onInputValueChange = { viewModel.validateCharCount( - characterCount = characterCount, - input = it, - errorText = null, - id = 0 - ) }, + value = placeholderValue, + onInputValueChange = { + viewModel.validateCharCount( + characterCount = characterCount, + input = it, + errorText = null, + id = 0 + ) + placeholderValue = it + }, errorText = viewModel.textInputErrorCharCount.collectAsStateWithLifecycle().value, labelText = stringResource(id = R.string.text_input_placeholder_label), hintText = stringResource(id = R.string.text_input_placeholder_hint), @@ -61,33 +74,46 @@ fun TextInputViewScreen() { ExamplesSlot { HmrcCardView { TextInputView( + value = example1Value, modifier = Modifier.padding( horizontal = HmrcTheme.dimensions.hmrcSpacing16, vertical = HmrcTheme.dimensions.hmrcSpacing24, ), - onInputValueChange = { viewModel.validateCharCount(5, it, errorTextEx1, 1) }, + onInputValueChange = { + viewModel.validateCharCount(5, it, errorTextEx1, 1) + example1Value = it + }, errorText = viewModel.textInputErrorCharCount1.collectAsStateWithLifecycle().value, labelText = stringResource(R.string.text_input_example_1_hint), labelContentDescription = stringResource(R.string.text_input_example_1_content_description), characterCount = 5, + maxChars = 5 ) TextInputView( + value = example2Value, modifier = Modifier.padding( horizontal = HmrcTheme.dimensions.hmrcSpacing16, vertical = HmrcTheme.dimensions.hmrcSpacing24, ), - onInputValueChange = { viewModel.isEmptyValidation(it, errorTextEx2, 0) }, + onInputValueChange = { + viewModel.isEmptyValidation(it, errorTextEx2, 0) + example2Value = it + }, errorText = viewModel.textInputError.collectAsStateWithLifecycle().value, hintText = stringResource(id = R.string.text_input_example_2_hint) ) TextInputView( + value = example3Value, modifier = Modifier.padding( horizontal = HmrcTheme.dimensions.hmrcSpacing16, vertical = HmrcTheme.dimensions.hmrcSpacing24, ), - onInputValueChange = { viewModel.isEmptyValidation(it, errorTextEx3, 1) }, + onInputValueChange = { + viewModel.isEmptyValidation(it, errorTextEx3, 1) + example3Value = it + }, errorText = viewModel.textInputErrorEmptyValidation.collectAsStateWithLifecycle().value, labelText = stringResource(R.string.text_input_example_3_hint), singleLine = true diff --git a/sample-compose-fragments/src/main/res/values/strings.xml b/sample-compose-fragments/src/main/res/values/strings.xml index c99c8bcd..daad2173 100644 --- a/sample-compose-fragments/src/main/res/values/strings.xml +++ b/sample-compose-fragments/src/main/res/values/strings.xml @@ -281,7 +281,7 @@ Hint Placeholder Pay amount - The value can be a decimal + The value can be a decimal but only 4 chars long Pay amount (pounds) The value must not be a decimal Pay amount (pounds)