setSelectionRange function

void setSelectionRange(
  1. Element? input,
  2. int start,
  3. int end,
  4. [String? direction]
)

Custom implementation to prevent the error that TextInputElementBase.setSelectionRange throws when called on an EmailInputElement or NumberInputElement since ONLY Chrome does not support it.

A warning will be displayed in the console instead of an error.

Example that will throw an exception in Chrome: InputElement inputNodeRef;

// This will throw an exception in Chrome when the node is focused.
renderEmailInput() {
  return (Dom.input()
    ..type = 'email'
    ..onFocus = (_) {
      inputNodeRef.setSelectionRange(inputNodeRef.value.length, inputNodeRef.value.length);
    }
    ..ref = (instance) { inputNodeRef = instance; }
  )();
}

Example that will not throw: InputElement inputNodeRef;

// This will not throw an exception - and will work in all
// browsers except Chrome until
// https://bugs.chromium.org/p/chromium/issues/detail?id=324360
// is fixed.
renderChromeSafeEmailInput() {
  return (Dom.input()
    ..type = 'email'
    ..onFocus = (_) {
      setSelectionRange(inputNodeRef, inputNodeRef.value.length, inputNodeRef.value.length);
    }
    ..ref = (instance) { inputNodeRef = instance; }
  )();
}

See: bugs.chromium.org/p/chromium/issues/detail?id=324360

Implementation

void setSelectionRange(/* TextInputElement | TextAreaElement */Element? input, int start, int end, [String? direction]) {
  if (input is TextAreaElement) {
    input.setSelectionRange(start, end, direction);
  } else if (input is InputElement && supportsSelectionRange(input)) {
    if (browser.isChrome || browser.isFirefox) {
      final inputType = input.getAttribute('type');

      if (inputType == 'email' || inputType == 'number') {
        assert(ValidationUtil.warn(unindent(
            '''
            Google Chrome does not support `setSelectionRange` on email or number inputs.
            See: https://bugs.chromium.org/p/chromium/issues/detail?id=324360
            '''
        ), input));

        return;
      }
    }

    input.setSelectionRange(start, end, direction);
  } else {
    throw ArgumentError.value(input, 'input', 'must be an instance of `TextInputElementBase`, `NumberInputElement` or `TextAreaElement`');
  }
}