Derek Toub
Derek Toub

Reputation: 11

Samsung keyboard cursor position issue JS setSelectionRange

This angular directive auto-inserts commas every three digits in number input fields (e.g. "1000" becomes "1,000"). It preserves cursor position correctly in all browsers I have tested, except on Samsung phones with the Samsung keyboard, for example the Galaxy S8 running Android 7.0, Samsung experience version 8.1.

On Samsung, if I type "1000", the comma is inserted, and my cursor ends up between the tens and ones position, when it should be all the way to the right.

Is there any known fix for this issue?

angular.module('someWebApp')
  .directive('commaInput', function() {
  return {
    require: 'ngModel',
    link: function(scope, element, attrs, ngModelController) {
      var el = element[0];

      function clean(x) {
      while (x.toString().indexOf(",") != -1)
      {
        x = x.replace(",", "");
      }
      return x.replace(/\B(?=(?:\d{3})+(?!\d))/g, ",");
    }

      ngModelController.$parsers.push(function(val) {
        var cleaned = clean(val);

        // Avoid infinite loop of $setViewValue <-> $parsers
        if (cleaned === val) return val;

        var start = el.selectionStart + cleaned.length - val.length;
        var end = el.selectionEnd + cleaned.length - val.length;

        // element.val(cleaned) does not behave with
        // repeated invalid elements
        ngModelController.$setViewValue(cleaned);
        ngModelController.$render();

        el.setSelectionRange(start, end);
        return cleaned;
      });
    }
  }
});

The html input uses this directive (comma-input) and has type="tel".

Upvotes: 1

Views: 219

Answers (1)

Benjamin L&#252;scher
Benjamin L&#252;scher

Reputation: 412

This really seems to be a problem with some devices. I had a simmilar problem on a Samsung S7 device. My only solution which worked was pushing the setSelectionRange() method into a setTimeout().

setTimeout(() => {
    el.setSelectionRange(selStart, selEnd);
});

The millisecond param on the setTimeout method can be omitted as we don't need to wait before execution.

Upvotes: 0

Related Questions