From 0dfe4e86ad0d693e1a87c06525a963469d3569f0 Mon Sep 17 00:00:00 2001 From: Di Da Date: Mon, 14 Oct 2019 14:51:45 -0700 Subject: [PATCH 1/3] Support onSubmitEditing event --- packages/E2ETest/app/Consts.ts | 3 ++- packages/E2ETest/app/TestPages.ts | 11 +++++--- packages/E2ETest/app/TextInputTestPage.tsx | 4 +-- .../E2ETest/wdio/pages/TextInputTestPage.ts | 14 +++++++++++ packages/E2ETest/wdio/test/testInput.spec.ts | 8 ++++++ vnext/ReactUWP/Views/TextInputViewManager.cpp | 25 +++++++++++++++++++ 6 files changed, 59 insertions(+), 6 deletions(-) diff --git a/packages/E2ETest/app/Consts.ts b/packages/E2ETest/app/Consts.ts index 541fb2cb163..05b0746b41c 100644 --- a/packages/E2ETest/app/Consts.ts +++ b/packages/E2ETest/app/Consts.ts @@ -12,6 +12,7 @@ export const UNKNOWN_TESTPAGE = 'UnknownTestPage'; export const TEXTINPUT_TESTPAGE = 'TextInputTestPage'; export const TEXTINPUT_ON_TEXTINPUT = 'TextInput'; +export const PREVTEXT_ON_TEXTINPUT = 'PrevTextInput'; export const ML_TEXTINPUT_ON_TEXTINPUT = 'TextInputMultiLine'; // LoginTestPage @@ -23,4 +24,4 @@ export const LOGINRESULT_ON_LOGIN = 'Result'; export const SHOWPASSWORD_ON_LOGIN = 'ShowPassword'; // Accessibility -export const ACCESSBILITY_TESTPAGE = 'AccessiblityTestPage'; \ No newline at end of file +export const ACCESSBILITY_TESTPAGE = 'AccessiblityTestPage'; diff --git a/packages/E2ETest/app/TestPages.ts b/packages/E2ETest/app/TestPages.ts index ce6c40e4420..113fae5d2b7 100644 --- a/packages/E2ETest/app/TestPages.ts +++ b/packages/E2ETest/app/TestPages.ts @@ -6,7 +6,12 @@ import * as React from 'react'; import { TextInputTestPage } from './TextInputTestPage'; import { UnknownPage } from './UnknownPage'; -import { TEXTINPUT_TESTPAGE, UNKNOWN_TESTPAGE, LOGIN_TESTPAGE, ACCESSBILITY_TESTPAGE } from './Consts'; +import { + TEXTINPUT_TESTPAGE, + UNKNOWN_TESTPAGE, + LOGIN_TESTPAGE, + ACCESSBILITY_TESTPAGE, +} from './Consts'; import { LoginTestPage } from './LoginTestPage'; import { AccessibilityTestPage } from './AccessibilityTestPage'; @@ -30,13 +35,13 @@ const TestPages: ITestPage[] = [ { testId: ACCESSBILITY_TESTPAGE, description: 'Accessiblity Test Page', - content: AccessibilityTestPage + content: AccessibilityTestPage, }, { testId: UNKNOWN_TESTPAGE, description: 'Unknown Page', content: UnknownPage, - } + }, ]; export default TestPages; diff --git a/packages/E2ETest/app/TextInputTestPage.tsx b/packages/E2ETest/app/TextInputTestPage.tsx index 5dac4efc93c..ffc92034ac6 100644 --- a/packages/E2ETest/app/TextInputTestPage.tsx +++ b/packages/E2ETest/app/TextInputTestPage.tsx @@ -6,7 +6,7 @@ import React from 'react'; import {Text, TextInput, View} from 'react-native'; -import {TEXTINPUT_ON_TEXTINPUT, ML_TEXTINPUT_ON_TEXTINPUT} from './Consts'; +import {TEXTINPUT_ON_TEXTINPUT, ML_TEXTINPUT_ON_TEXTINPUT, PREVTEXT_ON_TEXTINPUT} from './Consts'; interface ITextInputTestPageState { curText: string; @@ -75,7 +75,7 @@ export class TextInputTestPage extends React.Component< /> curText: {this.state.curText} - prev: {this.state.prevText} + prev: {this.state.prevText} prev2: {this.state.prev2Text}) prev3: {this.state.prev3Text} diff --git a/packages/E2ETest/wdio/pages/TextInputTestPage.ts b/packages/E2ETest/wdio/pages/TextInputTestPage.ts index 782438703f6..f43ef9d9f75 100644 --- a/packages/E2ETest/wdio/pages/TextInputTestPage.ts +++ b/packages/E2ETest/wdio/pages/TextInputTestPage.ts @@ -7,6 +7,7 @@ import { BasePage, By } from './BasePage'; import { TEXTINPUT_ON_TEXTINPUT, ML_TEXTINPUT_ON_TEXTINPUT, + PREVTEXT_ON_TEXTINPUT, } from '../../app/Consts'; class TextInputTestPage extends BasePage { @@ -18,6 +19,11 @@ class TextInputTestPage extends BasePage { this.textInput.setValue(text); } + clearAndEnterOnTextInput(text: string) { + this.textInput.setValue(text); + this.textInput.addValue('Enter'); + } + clearAndTypeOnMLTextInput(text: string) { this.multiLineTextInput.setValue(text); } @@ -28,6 +34,10 @@ class TextInputTestPage extends BasePage { this.multiLineTextInput.addValue(text); } + getTextInputPrevText() { + return this.prevTextInput.getText(); + } + getTextInputText() { return this.textInput.getText(); } @@ -40,6 +50,10 @@ class TextInputTestPage extends BasePage { return By(TEXTINPUT_ON_TEXTINPUT); } + private get prevTextInput() { + return By(PREVTEXT_ON_TEXTINPUT); + } + private get multiLineTextInput() { return By(ML_TEXTINPUT_ON_TEXTINPUT); } diff --git a/packages/E2ETest/wdio/test/testInput.spec.ts b/packages/E2ETest/wdio/test/testInput.spec.ts index cd6e56e80f0..c6b71142ac7 100644 --- a/packages/E2ETest/wdio/test/testInput.spec.ts +++ b/packages/E2ETest/wdio/test/testInput.spec.ts @@ -23,6 +23,14 @@ describe('First', () => { assert.equal(TextInputTestPage.getTextInputText(), 'def'); }); + it('Type abc on multiline TextInput then press Enter key', () => { + TextInputTestPage.clearAndEnterOnTextInput('abc'); + assert.equal( + TextInputTestPage.getTextInputPrevText(), + 'prev: onSubmitEditing text: abc' + ); + }); + it('Type abc on multiline TextInput', () => { TextInputTestPage.clearAndTypeOnMLTextInput('abc'); assert.equal(TextInputTestPage.getMLTextInputText(), 'abc'); diff --git a/vnext/ReactUWP/Views/TextInputViewManager.cpp b/vnext/ReactUWP/Views/TextInputViewManager.cpp index 7af210d4225..1ceac2af694 100644 --- a/vnext/ReactUWP/Views/TextInputViewManager.cpp +++ b/vnext/ReactUWP/Views/TextInputViewManager.cpp @@ -142,6 +142,7 @@ class TextInputShadowNode : public ShadowNodeBase { winrt::Control::GotFocus_revoker m_controlGotFocusRevoker{}; winrt::Control::LostFocus_revoker m_controlLostFocusRevoker{}; + winrt::Control::KeyDown_revoker m_controlKeyDownRevoker{}; winrt::Control::SizeChanged_revoker m_controlSizeChangedRevoker{}; winrt::Control::CharacterReceived_revoker m_controlCharacterReceivedRevoker{}; winrt::ScrollViewer::ViewChanging_revoker m_scrollViewerViewChangingRevoker{}; @@ -280,6 +281,28 @@ void TextInputShadowNode::registerEvents() { } }); + m_controlKeyDownRevoker = control.KeyDown( + winrt::auto_revoke, [=](auto &&, winrt::KeyRoutedEventArgs const &args) { + if (args.Key() == winrt::VirtualKey::Enter && !args.Handled()) { + auto instance = wkinstance.lock(); + folly::dynamic eventDataSubmitEditing = {}; + if (m_isTextBox) { + eventDataSubmitEditing = folly::dynamic::object("target", tag)( + "text", HstringToDynamic(control.as().Text())); + } else { + eventDataSubmitEditing = folly::dynamic::object("target", tag)( + "text", + HstringToDynamic(control.as().Password())); + } + if (!m_updating && instance != nullptr) { + instance->DispatchEvent( + tag, + "topTextInputSubmitEditing", + std::move(eventDataSubmitEditing)); + } + } + }); + if (m_isTextBox) { auto textBox = control.as(); m_textBoxSelectionChangedRevoker = @@ -628,6 +651,8 @@ folly::dynamic TextInputViewManager::GetExportedCustomDirectEventTypeConstants() folly::dynamic::object("registrationName", "onKeyPress"); directEvents["topTextInputOnScroll"] = folly::dynamic::object("registrationName", "onScroll"); + directEvents["topTextInputSubmitEditing"] = + folly::dynamic::object("registrationName", "onSubmitEditing"); return directEvents; } From 7b95f8e9c713ab903a529371bacf84c3d41b3e77 Mon Sep 17 00:00:00 2001 From: Di Da Date: Tue, 15 Oct 2019 14:45:40 -0700 Subject: [PATCH 2/3] Address PR comments --- vnext/ReactUWP/Views/TextInputViewManager.cpp | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/vnext/ReactUWP/Views/TextInputViewManager.cpp b/vnext/ReactUWP/Views/TextInputViewManager.cpp index 1ceac2af694..523e65c540c 100644 --- a/vnext/ReactUWP/Views/TextInputViewManager.cpp +++ b/vnext/ReactUWP/Views/TextInputViewManager.cpp @@ -284,17 +284,18 @@ void TextInputShadowNode::registerEvents() { m_controlKeyDownRevoker = control.KeyDown( winrt::auto_revoke, [=](auto &&, winrt::KeyRoutedEventArgs const &args) { if (args.Key() == winrt::VirtualKey::Enter && !args.Handled()) { - auto instance = wkinstance.lock(); - folly::dynamic eventDataSubmitEditing = {}; - if (m_isTextBox) { - eventDataSubmitEditing = folly::dynamic::object("target", tag)( - "text", HstringToDynamic(control.as().Text())); - } else { - eventDataSubmitEditing = folly::dynamic::object("target", tag)( - "text", - HstringToDynamic(control.as().Password())); - } - if (!m_updating && instance != nullptr) { + if (auto instance = wkinstance.lock()) { + folly::dynamic eventDataSubmitEditing = {}; + if (m_isTextBox) { + eventDataSubmitEditing = folly::dynamic::object("target", tag)( + "text", + HstringToDynamic(control.as().Text())); + } else { + eventDataSubmitEditing = folly::dynamic::object("target", tag)( + "text", + HstringToDynamic( + control.as().Password())); + } instance->DispatchEvent( tag, "topTextInputSubmitEditing", From e4148df2e215c3135a4713170da934a2bac97358 Mon Sep 17 00:00:00 2001 From: Di Da Date: Tue, 15 Oct 2019 16:04:41 -0700 Subject: [PATCH 3/3] Change files --- ...native-windows-2019-10-15-16-04-40-submitediting.json | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 change/react-native-windows-2019-10-15-16-04-40-submitediting.json diff --git a/change/react-native-windows-2019-10-15-16-04-40-submitediting.json b/change/react-native-windows-2019-10-15-16-04-40-submitediting.json new file mode 100644 index 00000000000..869f434bf1e --- /dev/null +++ b/change/react-native-windows-2019-10-15-16-04-40-submitediting.json @@ -0,0 +1,9 @@ +{ + "type": "prerelease", + "comment": "Support onSubmitEditing event", + "packageName": "react-native-windows", + "email": "dida@ntdev.microsoft.com", + "commit": "02aa39cf03c6b1b9e0d40e4b50fe463d864b8831", + "date": "2019-10-15T23:04:40.770Z", + "file": "D:\\react-native-windows\\change\\react-native-windows-2019-10-15-16-04-40-submitediting.json" +} \ No newline at end of file