-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
iOS/Android: Text input error for screenreaders #12
Comments
This comment was marked as outdated.
This comment was marked as outdated.
Change of error state from onChangeText show/hides a TextInput errorExpected Result: Actual Result: Applying changes from with facebook/react-native#29070 fixes the issue. click to open test
function ErrorExample(): React.Node {
const [text, setText] = React.useState('');
const [error, setError] = React.useState(null);
const textinput = React.useRef(null);
return (
<>
<Button title="create error" onPress={() => setError('button')} />
<TextInput
ref={textinput}
errorMessage={error}
onBlur={() => setError('onBlur')}
onChangeText={newText => {
setText(newText);
setError(newText === 'error' ? 'this input is invalid' : null);
}}
value={text}
/>
</>
);
} |
Test Cases of the functionality (Android - Fabric)error added onChangeText
2022-04-21.17-03-38.mp4error added on onEndEditing
2022-04-21.17-04-45.mp4 |
This comment was marked as resolved.
This comment was marked as resolved.
understanding onChangeText callback
onChangeText is disabled in ReactAndroid by using replace instead of setText instead this callback controls onChangeText solved with fabOnReact/react-native@d3d54e1 |
allow to display error message on TextInput triggered in a onChangeText callback. Fixes issue explained in: fabOnReact/react-native-notes#12 (comment) Related links: fabOnReact/react-native-notes#12 (comment) d3d54e1
allow to display error message on TextInput triggered in a onChangeText callback. Fixes issue explained in: fabOnReact/react-native-notes#12 (comment) Related links: fabOnReact/react-native-notes#12 (comment) d3d54e1
allow to display error message on TextInput triggered in a onChangeText callback. Fixes issue explained in: fabOnReact/react-native-notes#12 (comment) Related links: fabOnReact/react-native-notes#12 (comment) d3d54e1
AndroidTextInputProps and AndroidTextInputState.cpp
fabOnReact/react-native@5abe584 ReactEditText - need to add the errorMessageAndroid to AndroidTextInputState I added errorMessageAndroid prop to but needs to be added also to AndroidTextInputState so the StateWrapper includes also the errorMessageAndroid need to follow similar implementation of underlineColorAndroid |
This comment was marked as resolved.
This comment was marked as resolved.
passing mock values to AndroidTextInputShadowNode.cpp
to pass mock value of errorMessageAndroid to the constructor, I would need to generate a string of type The method createFromAscii could be used to generate a random string. Relevant links:
|
adding errorMessageAndroid to c++ state
adding newState["errorMessageAndroid"] = "my error message"; adds the error message in the java ReactTextInputManager udpateState method |
This comment was marked as resolved.
This comment was marked as resolved.
see facebook/react-native#33468 (comment) TextInputState paragraphAttributes and textAttributes The above state is added here The functionality was initially introduced by adding the StateParagraph component commit 06ce568 to the state.
and then commit fabOnReact/react-native@13db6cb
The AndroidTextInputState seems composed of two components:
Debug Statements fabOnReact/react-native@1e54f76 |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
setting the TextInput errorMessage state with setTextAndSelection Java API from JavaScriptRelated links
Expected Result: Actual Result: click to open code used in the test
function ErrorExample(): React.Node {
const [text, setText] = React.useState('');
const [error, setError] = React.useState(null);
return (
<>
<Button onPress={() => setError('button')} title="Press to set error" />
<Text>
Type error in the below TextInput to display an error message.
</Text>
<TextInput
maximumNumberOfLines={2}
accessibilityRole="button"
hyphenationFrequency="normal"
errorMessageAndroid={error}
onBlur={() => setError('onBlur')}
onEndEditing={() => setError('onEndEditing')}
onChangeText={newText => {
setText(newText);
if (newText === 'error') {
setError('this input is invalid');
} else if (error !== 'onBlur') {
setError(null);
}
}}
value={text}
style={[styles.default, {height: 50}]}
/>
</>
);
} click to open recording of test case
2022-03-30.11-49-06.mp4 |
This comment was marked as off-topic.
This comment was marked as off-topic.
Test Cases of the functionality (Paper) after removing changes to .cpp libs2022-05-12.19-45-17.mp4 |
xcode stuck when loading podsMy MacBook Pro has very limited storage (125GB model). I spend considerable amount of time saving storage and did the mistake of enabling iCloud. The files were stored on iCloud and xcode was having issues downloading them. I also experienced this on my new MacBook Pro, I enabled iCloud by mistake. Screen.Recording.2022-05-12.at.20.53.42.mov |
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
setMostRecentEventCount is called after invoking setScreeenreaderError
_onChange callback does the following:
useLayoutEffect does the following:
With the screenreaderError we don't receive a value from native (iOS or Android) that we want to over-ride. I think the issue here is we use setTextAndSelection to over-ride the native value (iOS, Android) of the text, but this over-rides also something else. I run a test with another prop textAlign. textAlign is will update if changed onChangeText callback and it is included ReactTextUpdate https://github.com/facebook/react-native/search?q=textAlign |
reapply the previous solution after doing a reset of the branch changes deleted are saved in branch https://github.com/facebook/react-native/compare/main...fabriziobertoglio1987:text-input-errors-set-text-and-selection?expand=1 Moving the head back to this commit facebook@29b99ba Reapply the solution for iOS announcing multiple times the errorMessage facebook@e0bdf61 facebook@3467c5d A similar problem was also detected on Android and solved with a similar solution fabOnReact/react-native-notes#12 (comment) The reset was done to remove the changes to the implementation which would use codegen.setTextAndSelection() instead of adding the prop to c++ Explained in detail here fabOnReact/react-native-notes#12 (comment) we have 2 types of data flow in the TextInput SCENARIO 1 Javascript <---> Native Android/iOS JavaScript receives in callback like onChangeText updates on the value of the text and selection position, then decides with an onLayoutEffect callback to over-ride those updates with the value kept in internal state. This is how JavaScript TextInput component works. SCENARIO 2 CPP <----> Native Android/iOS The state in CPP/Android/iOS keeps in sync. In this case, we don't receive any native update from Android/iOS on the value of the screenreaderError in Native side (not like for example the text value which is passed back to JavaScript with the _onChange callback). https://github.com/fabriziobertoglio1987/react-native/blob/f2e23215ca14c3c630aa931cdd114187589ac0fb/Libraries/Components/TextInput/TextInput.js#L1115 For this reason, I don't think is a good idea including the screenreaderError in the setTextAndSelection.
iOS - announcing error onChangeText and screenreader focus
HEAD fabOnReact/react-native@bb4597e new.test.low.quality.mp4 |
This comment was marked as resolved.
This comment was marked as resolved.
iOS - The screenreader announces the TextInput value after the errorMessage is cleared
source code for example
function ErrorExample(): React.Node {
const [text, setText] = React.useState('');
const [error, setError] = React.useState(null);
const [accessibilityInvalid, setAccessibilityInvalid] = React.useState(false);
return (
<>
<Button onPress={() => setError('button')} title="Press to set error" />
<Text>
Type error in the below TextInput to display an error message.
</Text>
<TextInput
accessibilityErrorMessage={error}
accessibilityInvalid={accessibilityInvalid}
// onBlur={() => setError('onBlur')}
// onEndEditing={() => setError('onEndEditing')}
onChangeText={newText => {
setText(newText);
if (newText === 'Error') {
setError('the newText is: ' + newText);
setAccessibilityInvalid(true);
} else if (newText === 'empty') {
setError(newText);
setAccessibilityInvalid(true);
} else if (newText === 'null') {
setError('');
setAccessibilityInvalid(false);
} else {
setError(newText);
setAccessibilityInvalid(false);
}
}}
value={text}
style={styles.default}
/>
</>
);
} |
iOS - Exception thrown while executing UI block: - [RCTTextView setOnAccessibiltyAction:]: unrecognized selector sent to instance (Paper) (main branch)
Issue experienced on main branch when opening the accessibility example. The second error displays |
iOS - accessibilityErrorMessage is not announced on Paper
Steps to solve this problem:
I was able to implement a solution in TextInput.js to trigger the accessibility announcement in JavaScript.
The implementation of accessibilityValue and accessibilityValueInternal should be enough for this functionality and I believe no native code needs to be added for iOS. |
Fabric and Paper use different implementations to handle diffing for props. Changes to native iOS implementation should be minimal, as the accessibilityValue prop is already implemented for iOS.
In Paper the accessibilityValue is set:
I was able to trigger the announcement correctly onChangeText (no on hover) using only JavaScript:
|
This comment was marked as resolved.
This comment was marked as resolved.
Implementation of TextInput Component on iOS RCTBaseTextInputView is a wrapper View around the UITextField: RCTBaseTextInputView does not implement backedTextInputView which needs to be over-ridden in RCTSinglelineTextInputView.
RCTUITextField is a iOS Component build on top of UITextField: Solution:
Issues:
Todo:
|
This comment was marked as off-topic.
This comment was marked as off-topic.
iOS - announce lastChar (not entire text) onChangeText and avoid multiple announcements (Fabric)
Commit fabOnReact/react-native@b53ed9d fixes the following issues on iOS Fabric (apply solution from Paper) 1)The error is announced, but not with the character onChangeText Related #12 (comment) #12 (comment) sourcecode
function AccessibilityErrorWithButtons(): React.Node {
const [text, setText] = React.useState('');
const [error, setError] = React.useState(null);
const [accessibilityInvalid, setAccessibilityInvalid] = React.useState(false);
return (
<View>
<RNTesterBlock>
<TextInput
accessibilityErrorMessage={error}
accessibilityInvalid={accessibilityInvalid}
onChangeText={newText => {
if (newText === 'Error') {
setError('this is the error');
setAccessibilityInvalid(true);
} else {
setError('');
setAccessibilityInvalid(false);
}
setText(newText);
}}
value={text}
style={styles.default}
/>
<Button
onPress={() => {
setError('This error is set with Button onPress callback');
}}
title="Press to set an accessibilityErrorMessage to a non-empty value"
/>
<Button
onPress={() => setAccessibilityInvalid(!accessibilityInvalid)}
title={`Press to set accessibilityInvalid to ${
accessibilityInvalid ? 'false' : 'true'
}`}
/>
<Button
onPress={() => setError('')}
title={`Press to set an empty error message`}
/>
</RNTesterBlock>
</View>
);
} low_quality.mp4 |
1)The error is announced, but not with the character onChangeText 2)The error is announced multiple times Test Case of this changes fabOnReact/react-native-notes#12 (comment)
iOS - announces or does not announce the accessibilityError through Button onPress (not onChangeText) (Fabric)
sourcecode
function AccessibilityErrorWithButtons(): React.Node {
const [text, setText] = React.useState('');
const [error, setError] = React.useState(null);
const [accessibilityInvalid, setAccessibilityInvalid] = React.useState(false);
return (
<View>
<RNTesterBlock>
<TextInput
accessibilityErrorMessage={error}
accessibilityInvalid={accessibilityInvalid}
onChangeText={newText => {
if (newText === 'Error') {
setError('this is the error');
setAccessibilityInvalid(true);
} else {
setError('');
setAccessibilityInvalid(false);
}
setText(newText);
}}
value={text}
style={styles.default}
/>
<Button
onPress={() => {
setError('This error is set with Button onPress callback');
}}
title="Press to set an accessibilityErrorMessage to a non-empty value"
/>
<Button
onPress={() => setAccessibilityInvalid(!accessibilityInvalid)}
title={`Press to set accessibilityInvalid to ${
accessibilityInvalid ? 'false' : 'true'
}`}
/>
<Button
onPress={() => setError('')}
title={`Press to set an empty error message`}
/>
</RNTesterBlock>
</View>
);
} first_low.mp4 |
iOS - the error is announced with accessibilityInvalid true and does not clear after typing text (onChangeText) (Fabric)
sourcecode
function AccessibilityErrorDoesNotClear(): React.Node {
const [text, setText] = React.useState('');
const [error, setError] = React.useState('');
const [accessibilityInvalid, setAccessibilityInvalid] = React.useState(false);
return (
<View>
<RNTesterBlock title="TextView without label">
<Text>Set an error, change textinput value and then announce it.</Text>
<TextInput
accessibilityErrorMessage={error}
accessibilityInvalid={accessibilityInvalid}
value={text}
onChangeText={newText => setText(newText)}
style={styles.default}
/>
<Text>
The value of the accessibilityErrorMessage prop is{' '}
{error.length > 0 ? error : 'empty error'}
</Text>
<Button
onPress={() => {
setError('This is an error');
}}
title="sets accessibilityErrorMessage to 'This is an error'"
/>
<Button
onPress={() => setAccessibilityInvalid(!accessibilityInvalid)}
title={`Press to set accessibilityInvalid to ${
accessibilityInvalid ? 'false' : 'true'
}`}
/>
</RNTesterBlock>
</View>
);
} second_low.mp4 |
Summary: **Android**: The functionality consists of calling the [AccessibilityNodeInfo#setError][10] and [#setContentInvalid][13] method to display the error message in the TextInput. **Fixes [https://github.com/facebook/react-native/issues/30848][51] - Adding an accessibilityErrorMessage prop to the TextInput Component**: **Android**: The prop accessibilityErrorMessage triggers the AccessibilityNodeInfo method [setError][10] which automatically sets the correct properties on the AccessibilityNodeInfo that will inform screen readers of this state. The method calls setContentInvalid(true) and setError(youErrorString) on the AccessibilityNodeInfo. **Fixes [https://github.com/facebook/react-native/issues/30859][52] - Detecting changes in the Error state (text inputs)** **Fabric - Android** - Adding accessibilityErrorMessage to field AndroidTextInputState. ReactTextInputManager and ReactEditText receive state updates both from [Javascript][32] and [cpp (fabric)][34]. - accessibilityErrorMessage is added to the fabric AndroidTextInputState field - The updates are received in the ReactAndroid API with method updateState from ReactTextInputManager - After updating the TextInput text with onChangeText, the update of the accessibilityErrorMessage is triggered with method maybeSetAccessibilityError which triggers [setError][10]. More info: - An explanation of [state updates between fabric and ReactAndroid for the TextInput component][34] - [ReactNative renderer state updates][35] **Paper - Android** - Adding accessibilityErrorMessage to ReactTextInputShadowNode to trigger updates in Paper renderer when accessibilityErrorMessage is changed within the onChange callback. Related Links (Android): - [In this diff I'm shipping and deleting mapBufferSerialization for Text measurement][101] - [This diff implement and integrates Mapbuffer into Fabric text measure system][39] - [Refactor ViewPropsMapBuffer -> general MapBuffer props mechanism][100] - [TextInput: support modifying TextInputs with multiple Fragments (Cxx side)][24] - [TextInput: keep C++ state in-sync with updated AttributedStrings in Java][23] - [AccessibilityNodeInfo#setError][11] - [Explanation on how TextInput calls SET_TEXT_AND_SELECTION in Java API][32] - [Fabric: convertRawProp was extended to accept an optional default value][27] - [understanding onChangeText callback][31] - [Editable method replace()][12] - [Change of error state from onChangeText show/hides a TextInput error][30] - [AndroidTextInput: support using commands instead of setNativeProps (native change)][25] - [TextInput: support editing completely empty TextInputs][26] - [[Android] Fix letters duplication when using autoCapitalize https://github.com/facebook/react-native/issues/29070][40] - [Support optional types for C++ TurboModules][28] - [discussion on using announceForAccessibility in ReactEditText][36] - [ fix annoucement delayed to next character][61] - [Announce accessibility state changes happening in the background][29] - [Refactor MountingManager into MountingManager + SurfaceMountingManager][37] iOS Functionalities are included in separate PR #35908 Documentation PR facebook/react-native-website#3010 Next PR [2/2 TextInput accessibilityErrorMessage (VoiceOver, iOS) https://github.com/facebook/react-native/issues/35908](https://github.com/facebook/react-native/pull/35908) Related facebook/react-native-deprecated-modules#18 ## Changelog [Android] [Added] - Adding TextInput prop accessibilityErrorMessage to announce with TalkBack screenreaders Pull Request resolved: #33468 Test Plan: **Android - 20 Jan 2023** #33468 (comment) **iOS - 20 Jan 2023** #33468 (comment) <details><summary>CLICK TO OPEN OLD VIDEO TEST CASES</summary> <p> **PR Branch - Android and iOS 24th June** [88]: Android - accessibilityValue announces correctly with/out errorMessage set with onChangeText or with outside event (Fabric) ([link][88]) **PR Branch - Android** [1]. Test Cases of the functionality (Fabric) ([link][1]) [2]. Test Cases of the functionality (Paper) ([link][2]) **Main Branch** [6]. Android - Runtime Error in main branch when passing value of 1 to TextInput placeholder prop ([link][6]) **Issues Solved** [7]. TalkBack error does not clear error on the next typed character when using onChangeText ([link][7]) **Other Tests** [8]. Setting the TextInput errorMessage state with setTextAndSelection Java API from JavaScript ([link][8]) [9]. Setting the TextInput errorMessage state from fabric TextInput internal state to Java ReactTextUpdate API ([link][9]) </p> </details> [1]: fabOnReact/react-native-notes#12 (comment) "Test Cases of the functionality (Android - Fabric)" [2]: fabOnReact/react-native-notes#12 (comment) "Test Cases of the functionality (Android - Paper)" [3]: fabOnReact/react-native-notes#12 (comment) "Test Cases of the functionality (iOS - Fabric)" [6]: fabOnReact/react-native-notes#12 (comment) "Runtime Error in main branch when passing value of 1 to TextInput placeholder prop" [7]: fabOnReact/react-native-notes#12 (comment) "TalkBack error announcement done on next typed character with onChangeText" [8]: fabOnReact/react-native-notes#12 (comment) "setting the TextInput errorMessage state with setTextAndSelection Java API from JavaScript" [9]: fabOnReact/react-native-notes#12 (comment) "Setting the TextInput errorMessage state from fabric TextInput internal state to Java ReactTextUpdate API" [10]: https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo#setError(java.lang.CharSequence) "AOSP setError" [11]: https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo#setError(java.lang.CharSequence) "AccessibilityNodeInfo#setError" [12]: https://github.com/aosp-mirror/platform_frameworks_base/blob/1ac46f932ef88a8f96d652580d8105e361ffc842/core/java/android/text/Editable.java#L28-L52 "Editable method replace" [13]: https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo#setContentInvalid(boolean) "setContentInvalid" [20]: 60b6c9b "draft implementation of android_errorMessage " [21]: 012d92d "add errorMessage to ReactTextUpdate and maybeSetAccessibilityError" [22]: fabOnReact@cad239b "rename android_errorMessage to errorMessageAndroid" [23]: fabOnReact@0bae474 "TextInput: keep C++ state in-sync with updated AttributedStrings in Java" [24]: fabOnReact@0556e86 "TextInput: support modifying TextInputs with multiple Fragments (Cxx side)" [25]: fabOnReact@7ab5eb4 "AndroidTextInput: support using commands instead of setNativeProps (native change)" [26]: fabOnReact@b9491b7 "TextInput: support editing completely empty TextInputs" [27]: fabOnReact@7f1ed68 "Fabric: convertRawProp was extended to accept an optional default value" [28]: 6e0fa5f "Support optional types for C++ TurboModules" [29]: fabOnReact@baa66f6 "Announce accessibility state changes happening in the background" [30]: fabOnReact/react-native-notes#12 (comment) "Change of error state from onChangeText show/hides a TextInput error" [31]: fabOnReact/react-native-notes#12 (comment) "understanding onChangeText callback" [32]: #29063 (comment) "Explanation on how TextInput calls SET_TEXT_AND_SELECTION in Java API" [33]: #33468 (comment) "Explanation of TextInput state management with fabric C++ and JAVA API" [34]: #33468 (comment) "state updates between fabric and ReactAndroid for the TextInput component" [35]: https://reactnative.dev/architecture/render-pipeline#react-native-renderer-state-updates "ReactNative renderer state updates" [35]: fabOnReact/react-native-notes#12 (comment) "Analysis on how AndroidTextInputState.cpp sends updates to ReactTextInputManager" [36]: #33468 (comment) "discussion on using announceForAccessibility in ReactEditText" [37]: fabOnReact@29eb632 "Refactor MountingManager into MountingManager + SurfaceMountingManager" [38]: fabOnReact@733f228 "Diff C++ props for Android consumption" [39]: fabOnReact@91b3f5d "This diff implement and integrates Mapbuffer into Fabric text measure system" [40]: #29070 "[Android] Fix letters duplication when using autoCapitalize #29070" [50]: fabOnReact/react-native-notes#12 "Notes from work on iOS/Android: Text input error for screenreaders #12" [51]: #30848 "iOS/Android: Text input error for screenreaders #30848" [52]: #30859 "Android: Error state change (text inputs) #30859" [61]: eb33c93 "fix annoucement delayed to next character" [70]: fabOnReact/react-native-notes#12 (comment) "iOS - Paper renderer does not update the accessibilityValue" [71]: fabOnReact/react-native-notes#12 (comment) "Test Cases of the functionality (Fabric) after removing changes to .cpp libs" [72]: fabOnReact/react-native-notes#12 (comment) "Test Cases of the functionality (Paper) after removing changes to .cpp libs" [73]: fabOnReact/react-native-notes#12 (comment) "iOS - announcing error onChangeText and screenreader focus" [74]: fabOnReact/react-native-notes#12 (comment) "iOS - The screenreader announces the TextInput value after the errorMessage is cleared" [75]: fabOnReact/react-native-notes#12 (comment) "iOS - Exception thrown while executing UI block: - [RCTTextView setOnAccessibiltyAction:]: unrecognized selector sent to instance (Paper) (main branch)" [76]: #30859 (comment) "iOS - announce lastChar (not entire text) onChangeText and avoid multiple announcements (Fabric)" [77]: #30859 (comment) "iOS - announces or does not announce the accessibilityError through Button onPress (not onChangeText) (Fabric)" [78]: #30859 (comment) "iOS - the error is announced with accessibilityInvalid true and does not clear after typing text (onChangeText) (Fabric)" [79]: #30848 (comment) "iOS - Exception thrown while executing UI block: - RCTUITextView setAccessibilityErrorMessage:]: unrecognized selector sent to instance (iOS - Paper on main branch)" [80]: fabOnReact@e13b9c6 "RCTTextField was spliited into two classes" [81]: fabOnReact@ee9697e "Introducing RCTBackedTextInputDelegate" [82]: fabOnReact@2dd2529 "Add option to hide context menu for TextInput" [83]: https://github.com/fabriziobertoglio1987/react-native/blob/343eea1e3150cf54d6f7727cd01d13eb7247c7f7/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentAccessibilityProvider.mm#L48-L72 "RCTParagraphComponentAccessibilityProvider accessibilityElements" [84]: https://github.com/fabriziobertoglio1987/react-native/blob/c8790a114f6f21774c43f0e9b9210e7b35d1c243/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm#L613 "RCTTextInputComponentView method _setAttributedString" [85]: https://github.com/fabriziobertoglio1987/react-native/blob/c8790a114f6f21774c43f0e9b9210e7b35d1c243/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm#L146 "RCTTextInputComponentView method updateProps" [86]: https://github.com/fabriziobertoglio1987/react-native/blob/c8790a114f6f21774c43f0e9b9210e7b35d1c243/Libraries/Text/TextInput/RCTBaseTextInputView.m#L150 "RCTBaseTextInputView setAttributedText" [87]: #30859 (comment) "iOS - accessibilityValue announces correctly with/out errorMessage set with onChangeText or with outside event" [88]: #30859 (comment) "Android - accessibilityValue announces correctly with/out errorMessage set with onChangeText or with outside event" [89]: #30859 (comment) "iOS - accessibilityValue announces correctly with/out errorMessage set with onChangeText or with outside event (Fabric)" [100]: fabOnReact@110b191 "Refactor ViewPropsMapBuffer -> general MapBuffer props mechanism" [101]: fabOnReact@22b6e1c "In this diff I'm shipping and deleting mapBufferSerialization for Text measurement" Reviewed By: blavalla Differential Revision: D38410635 Pulled By: lunaleaps fbshipit-source-id: cd80e9a1be8f5ca017c979d7907974cf72ca4777
…#33468) Summary: **Android**: The functionality consists of calling the [AccessibilityNodeInfo#setError][10] and [#setContentInvalid][13] method to display the error message in the TextInput. **Fixes [https://github.com/facebook/react-native/issues/30848][51] - Adding an accessibilityErrorMessage prop to the TextInput Component**: **Android**: The prop accessibilityErrorMessage triggers the AccessibilityNodeInfo method [setError][10] which automatically sets the correct properties on the AccessibilityNodeInfo that will inform screen readers of this state. The method calls setContentInvalid(true) and setError(youErrorString) on the AccessibilityNodeInfo. **Fixes [https://github.com/facebook/react-native/issues/30859][52] - Detecting changes in the Error state (text inputs)** **Fabric - Android** - Adding accessibilityErrorMessage to field AndroidTextInputState. ReactTextInputManager and ReactEditText receive state updates both from [Javascript][32] and [cpp (fabric)][34]. - accessibilityErrorMessage is added to the fabric AndroidTextInputState field - The updates are received in the ReactAndroid API with method updateState from ReactTextInputManager - After updating the TextInput text with onChangeText, the update of the accessibilityErrorMessage is triggered with method maybeSetAccessibilityError which triggers [setError][10]. More info: - An explanation of [state updates between fabric and ReactAndroid for the TextInput component][34] - [ReactNative renderer state updates][35] **Paper - Android** - Adding accessibilityErrorMessage to ReactTextInputShadowNode to trigger updates in Paper renderer when accessibilityErrorMessage is changed within the onChange callback. Related Links (Android): - [In this diff I'm shipping and deleting mapBufferSerialization for Text measurement][101] - [This diff implement and integrates Mapbuffer into Fabric text measure system][39] - [Refactor ViewPropsMapBuffer -> general MapBuffer props mechanism][100] - [TextInput: support modifying TextInputs with multiple Fragments (Cxx side)][24] - [TextInput: keep C++ state in-sync with updated AttributedStrings in Java][23] - [AccessibilityNodeInfo#setError][11] - [Explanation on how TextInput calls SET_TEXT_AND_SELECTION in Java API][32] - [Fabric: convertRawProp was extended to accept an optional default value][27] - [understanding onChangeText callback][31] - [Editable method replace()][12] - [Change of error state from onChangeText show/hides a TextInput error][30] - [AndroidTextInput: support using commands instead of setNativeProps (native change)][25] - [TextInput: support editing completely empty TextInputs][26] - [[Android] Fix letters duplication when using autoCapitalize https://github.com/facebook/react-native/issues/29070][40] - [Support optional types for C++ TurboModules][28] - [discussion on using announceForAccessibility in ReactEditText][36] - [ fix annoucement delayed to next character][61] - [Announce accessibility state changes happening in the background][29] - [Refactor MountingManager into MountingManager + SurfaceMountingManager][37] iOS Functionalities are included in separate PR facebook#35908 Documentation PR facebook/react-native-website#3010 Next PR [2/2 TextInput accessibilityErrorMessage (VoiceOver, iOS) https://github.com/facebook/react-native/issues/35908](https://github.com/facebook/react-native/pull/35908) Related facebook/react-native-deprecated-modules#18 ## Changelog [Android] [Added] - Adding TextInput prop accessibilityErrorMessage to announce with TalkBack screenreaders Pull Request resolved: facebook#33468 Test Plan: **Android - 20 Jan 2023** facebook#33468 (comment) **iOS - 20 Jan 2023** facebook#33468 (comment) <details><summary>CLICK TO OPEN OLD VIDEO TEST CASES</summary> <p> **PR Branch - Android and iOS 24th June** [88]: Android - accessibilityValue announces correctly with/out errorMessage set with onChangeText or with outside event (Fabric) ([link][88]) **PR Branch - Android** [1]. Test Cases of the functionality (Fabric) ([link][1]) [2]. Test Cases of the functionality (Paper) ([link][2]) **Main Branch** [6]. Android - Runtime Error in main branch when passing value of 1 to TextInput placeholder prop ([link][6]) **Issues Solved** [7]. TalkBack error does not clear error on the next typed character when using onChangeText ([link][7]) **Other Tests** [8]. Setting the TextInput errorMessage state with setTextAndSelection Java API from JavaScript ([link][8]) [9]. Setting the TextInput errorMessage state from fabric TextInput internal state to Java ReactTextUpdate API ([link][9]) </p> </details> [1]: fabOnReact/react-native-notes#12 (comment) "Test Cases of the functionality (Android - Fabric)" [2]: fabOnReact/react-native-notes#12 (comment) "Test Cases of the functionality (Android - Paper)" [3]: fabOnReact/react-native-notes#12 (comment) "Test Cases of the functionality (iOS - Fabric)" [6]: fabOnReact/react-native-notes#12 (comment) "Runtime Error in main branch when passing value of 1 to TextInput placeholder prop" [7]: fabOnReact/react-native-notes#12 (comment) "TalkBack error announcement done on next typed character with onChangeText" [8]: fabOnReact/react-native-notes#12 (comment) "setting the TextInput errorMessage state with setTextAndSelection Java API from JavaScript" [9]: fabOnReact/react-native-notes#12 (comment) "Setting the TextInput errorMessage state from fabric TextInput internal state to Java ReactTextUpdate API" [10]: https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo#setError(java.lang.CharSequence) "AOSP setError" [11]: https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo#setError(java.lang.CharSequence) "AccessibilityNodeInfo#setError" [12]: https://github.com/aosp-mirror/platform_frameworks_base/blob/1ac46f932ef88a8f96d652580d8105e361ffc842/core/java/android/text/Editable.java#L28-L52 "Editable method replace" [13]: https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo#setContentInvalid(boolean) "setContentInvalid" [20]: facebook@60b6c9b "draft implementation of android_errorMessage " [21]: facebook@012d92d "add errorMessage to ReactTextUpdate and maybeSetAccessibilityError" [22]: fabOnReact@cad239b "rename android_errorMessage to errorMessageAndroid" [23]: fabOnReact@0bae474 "TextInput: keep C++ state in-sync with updated AttributedStrings in Java" [24]: fabOnReact@0556e86 "TextInput: support modifying TextInputs with multiple Fragments (Cxx side)" [25]: fabOnReact@7ab5eb4 "AndroidTextInput: support using commands instead of setNativeProps (native change)" [26]: fabOnReact@b9491b7 "TextInput: support editing completely empty TextInputs" [27]: fabOnReact@7f1ed68 "Fabric: convertRawProp was extended to accept an optional default value" [28]: facebook@6e0fa5f "Support optional types for C++ TurboModules" [29]: fabOnReact@baa66f6 "Announce accessibility state changes happening in the background" [30]: fabOnReact/react-native-notes#12 (comment) "Change of error state from onChangeText show/hides a TextInput error" [31]: fabOnReact/react-native-notes#12 (comment) "understanding onChangeText callback" [32]: facebook#29063 (comment) "Explanation on how TextInput calls SET_TEXT_AND_SELECTION in Java API" [33]: facebook#33468 (comment) "Explanation of TextInput state management with fabric C++ and JAVA API" [34]: facebook#33468 (comment) "state updates between fabric and ReactAndroid for the TextInput component" [35]: https://reactnative.dev/architecture/render-pipeline#react-native-renderer-state-updates "ReactNative renderer state updates" [35]: fabOnReact/react-native-notes#12 (comment) "Analysis on how AndroidTextInputState.cpp sends updates to ReactTextInputManager" [36]: facebook#33468 (comment) "discussion on using announceForAccessibility in ReactEditText" [37]: fabOnReact@29eb632 "Refactor MountingManager into MountingManager + SurfaceMountingManager" [38]: fabOnReact@733f228 "Diff C++ props for Android consumption" [39]: fabOnReact@91b3f5d "This diff implement and integrates Mapbuffer into Fabric text measure system" [40]: facebook#29070 "[Android] Fix letters duplication when using autoCapitalize facebook#29070" [50]: fabOnReact/react-native-notes#12 "Notes from work on iOS/Android: Text input error for screenreaders facebook#12" [51]: facebook#30848 "iOS/Android: Text input error for screenreaders facebook#30848" [52]: facebook#30859 "Android: Error state change (text inputs) facebook#30859" [61]: facebook@eb33c93 "fix annoucement delayed to next character" [70]: fabOnReact/react-native-notes#12 (comment) "iOS - Paper renderer does not update the accessibilityValue" [71]: fabOnReact/react-native-notes#12 (comment) "Test Cases of the functionality (Fabric) after removing changes to .cpp libs" [72]: fabOnReact/react-native-notes#12 (comment) "Test Cases of the functionality (Paper) after removing changes to .cpp libs" [73]: fabOnReact/react-native-notes#12 (comment) "iOS - announcing error onChangeText and screenreader focus" [74]: fabOnReact/react-native-notes#12 (comment) "iOS - The screenreader announces the TextInput value after the errorMessage is cleared" [75]: fabOnReact/react-native-notes#12 (comment) "iOS - Exception thrown while executing UI block: - [RCTTextView setOnAccessibiltyAction:]: unrecognized selector sent to instance (Paper) (main branch)" [76]: facebook#30859 (comment) "iOS - announce lastChar (not entire text) onChangeText and avoid multiple announcements (Fabric)" [77]: facebook#30859 (comment) "iOS - announces or does not announce the accessibilityError through Button onPress (not onChangeText) (Fabric)" [78]: facebook#30859 (comment) "iOS - the error is announced with accessibilityInvalid true and does not clear after typing text (onChangeText) (Fabric)" [79]: facebook#30848 (comment) "iOS - Exception thrown while executing UI block: - RCTUITextView setAccessibilityErrorMessage:]: unrecognized selector sent to instance (iOS - Paper on main branch)" [80]: fabOnReact@e13b9c6 "RCTTextField was spliited into two classes" [81]: fabOnReact@ee9697e "Introducing RCTBackedTextInputDelegate" [82]: fabOnReact@2dd2529 "Add option to hide context menu for TextInput" [83]: https://github.com/fabriziobertoglio1987/react-native/blob/343eea1e3150cf54d6f7727cd01d13eb7247c7f7/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentAccessibilityProvider.mm#L48-L72 "RCTParagraphComponentAccessibilityProvider accessibilityElements" [84]: https://github.com/fabriziobertoglio1987/react-native/blob/c8790a114f6f21774c43f0e9b9210e7b35d1c243/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm#L613 "RCTTextInputComponentView method _setAttributedString" [85]: https://github.com/fabriziobertoglio1987/react-native/blob/c8790a114f6f21774c43f0e9b9210e7b35d1c243/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm#L146 "RCTTextInputComponentView method updateProps" [86]: https://github.com/fabriziobertoglio1987/react-native/blob/c8790a114f6f21774c43f0e9b9210e7b35d1c243/Libraries/Text/TextInput/RCTBaseTextInputView.m#L150 "RCTBaseTextInputView setAttributedText" [87]: facebook#30859 (comment) "iOS - accessibilityValue announces correctly with/out errorMessage set with onChangeText or with outside event" [88]: facebook#30859 (comment) "Android - accessibilityValue announces correctly with/out errorMessage set with onChangeText or with outside event" [89]: facebook#30859 (comment) "iOS - accessibilityValue announces correctly with/out errorMessage set with onChangeText or with outside event (Fabric)" [100]: fabOnReact@110b191 "Refactor ViewPropsMapBuffer -> general MapBuffer props mechanism" [101]: fabOnReact@22b6e1c "In this diff I'm shipping and deleting mapBufferSerialization for Text measurement" Reviewed By: blavalla Differential Revision: D38410635 Pulled By: lunaleaps fbshipit-source-id: cd80e9a1be8f5ca017c979d7907974cf72ca4777
Issues facebook/react-native#30848 facebook/react-native#30859
PR facebook/react-native#33468
Branch facebook/react-native@main...fabriziobertoglio1987:text-input-errors
New Branch facebook/react-native@main...fabriziobertoglio1987:text-input-errors-build
Branch used for debugging with additional history facebook/react-native@main...fabriziobertoglio1987:text-input-errors-build-debug-statements-2
Docs PR facebook/react-native-website#3010
Related https://developer.android.com/reference/android/widget/TextView#setError(java.lang.CharSequence) https://developer.android.com/reference/java/lang/CharSequence https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo#setError(java.lang.CharSequence) facebook/react-native#29070 facebook/react-native#29063 (comment) facebook/react-native#28952 #13
The text was updated successfully, but these errors were encountered: