Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ export function typeTextNatively(textField: TextField, text: string): void {
textField.android.clearFocus();
}

export function typeCharacterNatively(textField: TextField, character: string): void {
textField.android.append(character);
}

export function typeTextNativelyWithReturn(textField: TextField, text: string): void {
//
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ export declare function getNativeBackgroundColor(textField: textFieldModule.Text
export declare function getNativeTextAlignment(textField: textFieldModule.TextField): string;
export declare function getNativeFocus(textField: textFieldModule.TextField): boolean;
export declare function typeTextNatively(textField: textFieldModule.TextField, text: string): void;
export declare function typeCharacterNatively(textField: textFieldModule.TextField, character: string): void;
export declare function typeTextNativelyWithReturn(textField: textFieldModule.TextField, text: string): void;
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ export function typeTextNatively(textField: textFieldModule.TextField, text: str
textField.ios.delegate.textFieldDidEndEditing(textField.ios);
}

/** One keystroke as UIKit delivers it: the delegate is asked first, and the field changes only if it agrees. */
export function typeCharacterNatively(textField: textFieldModule.TextField, character: string): void {
const native: UITextField = textField.ios;
const range: NSRange = { location: native.text.length, length: 0 };
if (native.delegate.textFieldShouldChangeCharactersInRangeReplacementString(native, range, character)) {
native.text = NSString.stringWithString(native.text).stringByReplacingCharactersInRangeWithString(range, character);
}
}

export function typeTextNativelyWithReturn(textField: textFieldModule.TextField, text: string): void {
textField.nativeView.becomeFirstResponder();

Expand Down
25 changes: 23 additions & 2 deletions apps/automated/src/ui/text-field/text-field-tests.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as TKUnit from '../../tk-unit';
import * as helper from '../../ui-helper';
import { View, isIOS, StackLayout, Page, Color, Span, FormattedString, BindingOptions, Observable, TextField } from '@nativescript/core';
import { getNativeText, getNativeHint, typeTextNatively, typeTextNativelyWithReturn, getNativeSecure, getNativeFontSize, getNativeColor, getNativeBackgroundColor, getNativeTextAlignment, getNativePlaceholderColor, getNativeFocus } from './text-field-tests-native';
import { View, isIOS, StackLayout, Page, Color, Span, FormattedString, BindingOptions, Observable, PropertyChangeData, TextField } from '@nativescript/core';
import { getNativeText, getNativeHint, typeTextNatively, typeCharacterNatively, typeTextNativelyWithReturn, getNativeSecure, getNativeFontSize, getNativeColor, getNativeBackgroundColor, getNativeTextAlignment, getNativePlaceholderColor, getNativeFocus } from './text-field-tests-native';

// ### Binding two TextFields text property to observable view-model property.
// >> binding-text-property-textfield
Expand Down Expand Up @@ -223,6 +223,27 @@ export var testTextIsUpdatedWhenUserTypes = function () {
});
};

export var testTextWrittenByTextChangeListenerIsNotRepeatedByTheKeystroke = function () {
// Android's TextWatcher reports after the edit is applied, so only the iOS
// delegate can apply a keystroke on top of what the listener wrote.
if (!isIOS) {
return;
}
helper.buildUIAndRunTest(_createTextFieldFunc(), function (views: Array<View>) {
var textField = <TextField>views[0];
textField.text = '';
textField.on('textChange', (args: PropertyChangeData) => {
textField.text = String(args.value).toUpperCase();
});

typeCharacterNatively(textField, 'a');
typeCharacterNatively(textField, 'b');

TKUnit.assertEqual(textField.text, 'AB', 'TextField text');
TKUnit.assertEqual(getNativeText(textField), 'AB', 'TextField native text');
});
};

export var testSetHint = function () {
helper.buildUIAndRunTest(_createTextFieldFunc(), function (views: Array<View>) {
var textField = <TextField>views[0];
Expand Down
18 changes: 13 additions & 5 deletions packages/core/ui/text-field/index.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,12 +202,20 @@ export class TextField extends TextFieldBase {
// 2. emoji's should not replace value
// 3. convenient keyboard shortcuts should not replace value (eg, '.com')
const shouldReplaceString = (textField.secureTextEntry && this._firstEdit) || (delta > 1 && !isEmoji(replacementString) && delta !== replacementString.length);
let typedText: string;
if (shouldReplaceString) {
textProperty.nativeValueChange(this, replacementString);
} else {
if (range.location <= textField.text.length) {
const newText = NSString.stringWithString(textField.text).stringByReplacingCharactersInRangeWithString(range, replacementString);
textProperty.nativeValueChange(this, newText);
typedText = replacementString;
} else if (range.location <= textField.text.length) {
typedText = NSString.stringWithString(textField.text).stringByReplacingCharactersInRangeWithString(range, replacementString);
}
if (typedText !== undefined) {
textProperty.nativeValueChange(this, typedText);
// A textChange listener that set a different `text` has already
// pushed it to the native field; letting UIKit apply the typed
// replacement on top of it would repeat the keystroke.
if (this.text !== typedText) {
this._firstEdit = false;
return false;
}
}
}
Expand Down
Loading