Nick Mehrdad Babaki
Nick Mehrdad Babaki

Reputation: 12545

Failed to execute 'setSelectionRange' on 'HTMLInputElement': The input element's type ('number') does not support selection

I added the code below to select whole text when user click on input box:

<input type="number" onclick="this.setSelectionRange(0, this.value.length)" name="quantity" />

But I receive the error below:

Uncaught InvalidStateError: Failed to execute 'setSelectionRange' on 'HTMLInputElement': The input element's type ('number') does not support selection.

Upvotes: 45

Views: 55669

Answers (7)

Harish Kulkarni
Harish Kulkarni

Reputation: 1591

input type="number" doesn't support setSelectionRange

You can use: type="text" and inputmode="numeric", This will show a numeric keyboard for mobile users and supports setSelectionRange

    <input 
     type="text"
     inputmode="numeric"
     onclick="this.setSelectionRange(0, this.value.length)" 
     name="quantity" />

Upvotes: 4

Slavik Meltser
Slavik Meltser

Reputation: 10381

As a variation of Tri Q Tran's answer and make it a more generic one. This may be a better approach:

const element = document.createElement('input');
element.type = 'number';

(function(originalFn){
    element.setSelectionRange = function() {
        this.type = 'text';
        originalFn.apply(this, arguments);
        this.type = 'number';
    }
})(element.setSelectionRange);

Or if you don't mind contaminating the prototype, this is a more generic solution:

(function(originalFn){
    HTMLInputElement.prototype.setSelectionRange = function() {
        if ( this.type === 'number' ) {
            this.type = 'text';
            originalFn.apply(this, arguments);
            this.type = 'number';
        } else {
            originalFn.apply(this, arguments);
        }
    }
})(HTMLInputElement.prototype.setSelectionRange);

Upvotes: 6

Tri Q Tran
Tri Q Tran

Reputation: 5690

I know this is an old question, but I did find a good workaround without using the tel input type. By changing the input type from number to text before the selection, the error goes away and you get to keep all the benefits of the number input type.

  • tel allows text input, which may not work with numbers.
  • tel does not show the number "spinner" next to the input (only if you want it).
function onInputFocus(event) {
  const target = event.currentTarget;

  target.type = 'text';
  target.setSelectionRange(0, target.value.length);
  target.type = 'number';
}

Upvotes: 29

Avatar
Avatar

Reputation: 15186

Use input type="tel" instead.

For your example:

<input type="tel" onclick="this.setSelectionRange(0, this.value.length)" name="quantity" />

That will do the trick and avoid the error message.

And on mobile phones, it shows up the desired number pad.

Upvotes: 23

nub340
nub340

Reputation: 51

I kind of got this working in angular 1.5 using a nifty custom directive (see example below in typescript).

Since it appears there is no way to programmatically select the entire value while the input type="number", the strategy here is to temporarily change the input type from number to text while editing the value, then change it back to the original type on blur.

This results in behavior that differs slightly from the native behavior in that it will actually allow you to type in "invalid" data into the field. However, on blur, all of the browser's native number validation logic will kick in and prevent any invalid data from being submitted. I'm sure there's some other gotchas but it's works well enough in Chrome and FireFox for us so I thought I'd share.

/// Selects the entire input value on mouse click. 
/// Works with number and email input types.
export class SelectOnClick implements ng.IDirective {
    require = 'ngModel';
    restrict = 'A';
    private ogType: any

    constructor(private $window: ng.IWindowService) { }

    link = (scope: ng.IScope, element: any) => {

        element.on('click', () => {
            if (!this.$window.getSelection().toString()) {      
                this.ogType = element[0].type;
                element[0].type = 'text';
                element[0].setSelectionRange(0, element[0].value.length);
            }
        })

        element.on('blur', () => {
            element[0].type = this.ogType;
        })
    }

    static factory(): ng.IDirectiveFactory {
        var directive = ($window: ng.IWindowService) => new SelectOnClick($window);
        directive['$inject'] = ['$window'];
        return directive;
    }
} 

Upvotes: 1

Mike Miroshnikov
Mike Miroshnikov

Reputation: 41

The evt.target.select() selects content of input type="number" in Chrome, the "if" structure does the same on touch devices.

document.querySelector('.number_input').addEventListener('focus', function (evt) {
    evt.target.select();
    if ('ontouchstart' in window) {
      setTimeout(function() {
        evt.target.setSelectionRange(0, 9999);
      }, 1);
    }
}, true);

Unfortunately that "if" prevents that autoselect in Mac Safari, I don't know how to get the same result both in desktop browsers and mobile.

Upvotes: 3

Jordan Running
Jordan Running

Reputation: 106077

Just like the error message says, you can't use setSelectionRange with a number input. If you want to modify the selection using JavaScript, you'll have to use <input type="text"/> instead.

Upvotes: 3

Related Questions