web-dev-qa-db-fra.com

Sélectionner du texte sur le focus de saisie

J'ai une saisie de texte. Lorsque l'entrée reçoit le focus, je veux sélectionner le texte à l'intérieur de l'entrée.

Avec jQuery, je le ferais de cette façon:

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

J'ai cherché autour de moi pour essayer de trouver la méthode angulaire, mais la plupart des exemples que je trouve concernent une directive qui surveille un changement de propriété modale. Je suppose que j'ai besoin d'une directive qui surveille une entrée qui reçoit le focus. Comment je ferais ça? 

116
Billy Coover

La manière de procéder dans Angular consiste à créer une directive personnalisée qui effectue la sélection automatique pour vous.

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)
                }
            });
        }
    };
}]);

Appliquez la directive comme ceci:

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

View demo

Update1 : Suppression de la dépendance de jQuery.

Update2 : Restreindre comme attribut.

Update3 : Fonctionne dans Safari mobile. Permet de sélectionner une partie du texte (nécessite IE> 8).

211
Martin

Voici une directive améliorée qui évite de resélectionner le texte lorsque l'utilisateur clique pour positionner le curseur dans la zone de saisie.

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;
            });
        }
    };
})
43
Tamlyn

C'est une vieille réponse, pour Angular 1.x

La meilleure façon de le faire est d'utiliser la directive intégrée ng-click:

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

MODIFIER:

Comme JoshMB a gentiment rappelé; référencer des nœuds DOM dans Angular 1.2+ n'est plus autorisé. Donc, j'ai déplacé $event.target.select() dans le contrôleur:

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

Puis dans votre contrôleur:

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

Voici un exemple de violon .

38
Onur Yıldırım

Aucune des solutions proposées n'a bien fonctionné pour moi. Après de rapides recherches, j'ai trouvé ceci:

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;
            });
    }

  }

});

C'est un mélange de plusieurs solutions proposées, mais fonctionne à la fois sur le clic et le focus (pensez autofocus) et permet la sélection manuelle de la valeur partielle dans l'entrée.

15
xaralis

Pour moi, ng-click n'avait pas de sens, car vous ne pouviez jamais repositionner le curseur sans sélectionner à nouveau tout le texte, j'ai trouvé que c'était annulant. Ensuite, il est préférable d’utiliser ng-focus, car le texte n’est sélectionné que si l’entrée n’a pas été focalisée. Si vous cliquez à nouveau pour repositionner le curseur, le texte se désélectionne comme prévu et vous pouvez écrire entre les deux.

J'ai trouvé cette approche comme étant le comportement attendu de l'UX.

Utilisez ng-focus

Option 1: code séparé

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

et dans le contrôleur

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

Option 2: comme alternative, vous pouvez joindre le code ci-dessus dans ce "one-liner" (je n'ai pas testé cela, mais cela devrait fonctionner)

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

Dans angular 2, cela fonctionnait pour moi, à la fois sous Chrome et Firefox:

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

La réponse acceptée utilise l'événement click. Toutefois, si vous utilisez l'événement focus, seul le premier clic déclenche l'événement. Il se déclenche également lorsqu'une autre méthode est utilisée pour se concentrer sur l'entrée (comme appuyer sur l'onglet ou appeler le code dans le code).

Cela évite également de vérifier si l'élément est déjà concentré, comme le suggère la réponse de Tamlyn.

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

Aucune directive nécessaire, ajoutez simplement onfocus="this.select()" javascript natif à l'élément d'entrée ou à la zone de texte.

0
Adam Reis

La version modifiée qui a fonctionné pour moi . Le premier clic sélectionne le texte, le second clic sur le même élément désélectionne le texte 

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
Ola