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;
}