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 diff --git a/packages/E2ETest/app/Consts.ts b/packages/E2ETest/app/Consts.ts index 6f3bc0604a2..f29d3cfc1a2 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 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..523e65c540c 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,29 @@ void TextInputShadowNode::registerEvents() { } }); + m_controlKeyDownRevoker = control.KeyDown( + winrt::auto_revoke, [=](auto &&, winrt::KeyRoutedEventArgs const &args) { + if (args.Key() == winrt::VirtualKey::Enter && !args.Handled()) { + 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", + std::move(eventDataSubmitEditing)); + } + } + }); + if (m_isTextBox) { auto textBox = control.as(); m_textBoxSelectionChangedRevoker = @@ -628,6 +652,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; }