Выделить текст в фокусе ввода


121

У меня есть ввод текста. Когда ввод получает фокус, я хочу выделить текст внутри ввода.

С jQuery я бы сделал это так:

<input type="text" value="test" />
$("input[type=text]").click(function() {
    $(this).select();
    // would select "test" in this example
});

Я искал вокруг, пытаясь найти способ Angular, но большинство примеров, которые я нахожу, связаны с директивой, которая отслеживает изменение модального свойства. Я предполагаю, что мне нужна директива, которая отслеживает ввод, который получает фокус. Как мне это сделать?


Я понимаю, что вы хотите найти «способ Angular», но есть ли причина, по которой вы бы просто не стали этого делать <input type="text" value="test" onclick="this.select()" />?
— Josef P.

Ответы:


216

В Angular это можно сделать, создав настраиваемую директиву, которая выполняет автоматический выбор за вас.

module.directive('selectOnClick', ['$window', function ($window) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.on('click', function () {
                if (!$window.getSelection().toString()) {
                    // Required for mobile Safari
                    this.setSelectionRange(0, this.value.length)
                }
            });
        }
    };
}]);

Примените директиву следующим образом:

<input type="text" value="test" select-on-click />

View demo

Update1 : удалена зависимость jQuery.

Обновление 2 : ограничить как атрибут.

Update3 : работает в мобильном Safari. Позволяет выделить часть текста (требуется IE> 8).


10
Если вы хотите сделать это без jquery, замените element.click на element.bind ('click', function () {...} и element.select () на element [0] .select ()
— jack

3
Красиво и элегантно. Я бы также явно ограничил применение директивы в качестве атрибута (путем возврата литерала объекта и его настройки restrict: 'A'), поскольку эта директива направлена ​​на расширение поведения существующего элемента .
— Элиран Малка

@Martin есть идеи, как это сделать на открытой странице без щелчка пользователя? Проблема в том, что значение по умолчанию установлено в другом контроллере перед моей selectOnLoadдирективой link (). Но в link (), хотя область видимости уже заполнена, DOM элемента еще не синхронизирована с $ scope, поэтому, когда я вызываю select (), элемент все еще пуст и ничего не выделено. Единственный способ обойти, который я нашел, - это $ timeout, но я чувствую, что это может перестать работать с какой-то новой версией Angular.
— Дмитрий Лазерка

это хорошо работает на рабочем столе / android, но когда я пытаюсь использовать ipad, похоже, что это не работает. Есть ли здесь известная работа?
— ak85 01


44

Вот расширенная директива, которая позволяет избежать повторного выбора текста, когда пользователь щелкает, чтобы поместить курсор в поле ввода.

module.directive('selectOnClick', function () {
    return {
        restrict: 'A',
        link: function (scope, element) {
            var focusedElement;
            element.on('click', function () {
                if (focusedElement != this) {
                    this.select();
                    focusedElement = this;
                }
            });
            element.on('blur', function () {
                focusedElement = null;
            });
        }
    };
})

3
Я думаю , что этот ответ лучше , чем принято, поскольку это позволит устанавливают курсор на какую - то позицию в введенном тексте, но, как директива имеет собственную сферу - я предлагаю переименовать focusedElement переменной isElementFocused и хранить там правду или ложь
— Владимир Гордиенко

2
Я получаю Uncaught TypeError: undefined не является функцией на «this» для .select (); и да, jQuery 1.9.1 включен.
— Робби Смит,

@RobbieSmith Я опоздал на 3 года, но изменил все экземпляры thisна, element[0]и он должен работать. Я также рекомендую изменить его clickна, focusчтобы текст выделялся, если пользователь вкладывает вкладки во ввод, а не щелкает по нему.
— Лекс

40

Это старый ответ для Angular 1.x

Лучший способ сделать это - использовать ng-clickвстроенную директиву:

<input type="text" ng-model="content" ng-click="$event.target.select()" />

РЕДАКТИРОВАТЬ:

Как любезно напомнил JoshMB ; ссылки на узлы DOM в Angular 1.2+ больше не разрешены. Итак, я перешел $event.target.select()в контроллер:

<input type="text" ng-model="content" ng-click="onTextClick($event)" />

Затем в вашем контроллере:

$scope.onTextClick = function ($event) {
    $event.target.select();
};

Вот пример скрипки .


2
Насколько я могу судить, это больше не поддерживается. Angular выдает ошибку: «Ссылки на узлы DOM в выражениях Angular запрещены!». См. Эту ветку для получения дополнительной информации: groups.google.com/forum/#!topic/angular/bsTbZ86WAY4 . Однако директивный подход работает хорошо.
— JoshMB

Ты прав. Так обстоит дело с Angular 1.2+. Обновлю ответ.
— Онур Йылдырым

2
Изменения DOM нужно делать в директиве или нет?
— Piioo

По какой-то причине другие решения у меня не работали, но это сработало. Я думаю, проблема заключалась в том, что у меня уже была директива для элемента, в который я добавлял это событие щелчка.
— Precastic 08

Серьезно, даже onTextClick ($ event) теперь выдает ошибку. Помимо неинтуитивной природы этого зверя, во сколько нам обходятся эти неудобства с точки зрения производительности?
— jcalfee314

15

Ни одно из предложенных решений мне не подошло. После быстрого исследования я пришел к следующему:

module.directive('selectOnFocus', function ($timeout) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            var focusedElement = null;

            element.on('focus', function () {
                var self = this;
                if (focusedElement != self) {
                    focusedElement = self;
                    $timeout(function () {
                        self.select();
                    }, 10);
                }
            });

            element.on('blur', function () {
                focusedElement = null;
            });
    }

  }

});

Это сочетание нескольких предложенных решений, но работает как с щелчком, так и с фокусом (подумайте об автофокусе) и позволяет вручную выбирать частичное значение во вводе.


1
Исправлена ​​синтаксическая ошибка: последняя}); заменить на: } }; });
— Blackfire

Этот работает для input type = "number", и это здорово! Спасибо
— Луи

Эй, это работает для Ionic в Android, но не для iOS ... Вы не знаете, почему? Спасибо
— Луи

2
Похоже, вы оставили код, когда адаптировали его из onClick ... в чем смысл focusedElement?
— Лэнгдон

12

Для меня ng-click не имеет смысла, потому что вы никогда не сможете изменить положение курсора, не выделив весь текст снова, я обнаружил, что это раздражает. Тогда лучше использовать ng-focus, потому что текст выделяется только в том случае, если ввод не был сфокусирован, если вы щелкните еще раз, чтобы переместить курсор, тогда текст просто отменяется, как и ожидалось, и вы можете писать между ними.

Я обнаружил, что такой подход является ожидаемым поведением UX.

Используйте ng-focus

Вариант 1: отдельный код

<input type="text" ng-model="content" ng-focus="onTextFocus($event)" />

и в контроллере

$scope.onTextFocus = function ($event) {
  $event.target.select();
};

Вариант 2: в качестве альтернативы вы можете объединить приведенный выше код в этот «однострочный» (я не тестировал это, но он должен работать)

<input type="text" ng-model="content" ng-focus="$event.target.select()" />

Просто и это работает. Это также позволяет позиционировать курсор внутри выделенного текста, как описано выше.
— Пистолет-Пит

7

В angular 2 это сработало для меня, как в Chrome, так и в Firefox:

<input type="text" (mouseup)="$event.target.select()">

6

В принятом ответе используется событие щелчка, однако, если вы используете событие фокуса, только 1-й щелчок вызовет событие, и оно также срабатывает, когда используется какой-либо другой метод для фокусировки на вводе (например, нажатие вкладки или вызов фокуса в коде).

Это также делает ненужным проверять, сфокусирован ли элемент уже, как предлагает ответ Тамлина.

app.directive('selectOnClick', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.on('focus', function () {
                this.select();
            });
        }
    };
});

В Firefox 38.0.5 щелчок в середине текста сначала выделяет все, но затем удаляет выделение, так что это не сработает.
— user1338062 04

1
Вероятно, это никогда не сработает постоянно, без задержек this.select.
— Лэнгдон

6

Никаких директив не требуется, просто добавьте onfocus="this.select()"собственный javascript в элемент ввода или текстовую область.


1
почему так много людей придумывают все эти сложные ответы, когда самый простой способ здесь: D Спасибо, Адам
— SwissCoder

0

Модифицированная версия, которая работала у меня. Первый щелчок выделяет текст, второй щелчок по тому же элементу отменяет выделение текста

module.directive('selectOnClick', function ($timeout) {
return {
    restrict: 'A',
    link: function (scope, element, attrs) {
        var prevClickElem = null; //Last clicked element
        var ignorePrevNullOnBlur = false; //Ignoring the prevClickElem = null in Blur massege function

        element.on('click', function () {
            var self = this;
            if (prevClickElem != self) { //First click on new element
                prevClickElem = self; 
                $timeout(function () { //Timer
                    if(self.type == "number")
                        self.select();
                    else
                        self.setSelectionRange(0, self.value.length)
                }, 10);
            }
            else { //Second click on same element
                if (self.type == "number") {
                    ignorePrevNullOnBlur = true;
                    self.blur();
                }
                else
                    self.setSelectionRange(self.value.length, self.value.length); //deselect and set cursor on last pos
            }
        });

        element.on('blur', function () {
            if (ignorePrevNullOnBlur == true)
                ignorePrevNullOnBlur = false; //blur called from code handeling the second click 
            else
                prevClickElem = null; //We are leaving input box
        });
    }
}

})


0

Самый простой способ выделить весь текст при нажатии, фокусе или табуляции !!!:

<input (focus)="inputFocused($event)">

...

inputFocused(event: any){
    event.target.select()
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.