Seleziona il testo sullo stato attivo dell'input


121

Ho un input di testo. Quando l'input riceve il focus, desidero selezionare il testo all'interno dell'input.

Con jQuery lo farei in questo modo:

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

Ho cercato in giro per cercare di trovare il modo angolare, ma la maggior parte degli esempi che sto trovando hanno a che fare con una direttiva che sta guardando una proprietà modale per un cambiamento. Presumo di aver bisogno di una direttiva che cerchi un input che riceva il focus. Come potrei farlo?


Capisco che tu voglia trovare un "modo angolare", ma c'è qualche motivo per cui non lo faresti <input type="text" value="test" onclick="this.select()" />?
Josef P.

Risposte:


216

Il modo per farlo in Angular è creare una direttiva personalizzata che esegue la selezione automatica per te.

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

Applica la direttiva in questo modo:

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

View demo

Update1 : dipendenza jQuery rimossa.

Update2 : limita come attributo.

Update3 : funziona in Safari mobile. Permette la selezione di parte del testo (richiede IE> 8).


10
Se vuoi farlo senza jquery, cambia element.click in element.bind ('click', function () {...} e element.select () in element [0] .select ()
jack

3
Bello ed elegante. Vorrei anche limitare esplicitamente la direttiva da applicare come attributo (restituendo un oggetto letterale e impostazione restrict: 'A'), poiché questa direttiva mira ad estendere il comportamento di un elemento esistente .
Eliran Malka

@ Martin qualche idea su come farlo a pagina aperta, senza clic dell'utente? Il problema è che il valore predefinito è impostato in un altro controller prima della mia selectOnLoaddirettiva link (). Ma in link (), sebbene l'ambito sia già popolato, l'elemento DOM non è ancora sincronizzato con $ scope, quindi quando chiamo select (), l'elemento è ancora vuoto e non viene selezionato nulla. L'unico modo per aggirare quello che ho trovato è $ timeout, ma sento che può smettere di funzionare con qualche nuova versione di Angular.
Dzmitry Lazerka

funziona bene su desktop / Android ma quando provo su ipad non sembra funzionare. C'è un'opera conosciuta qui intorno?
ak85


44

Ecco una direttiva migliorata che evita di riselezionare il testo quando l'utente fa clic per posizionare il cursore nella casella di input.

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
Credo che questa risposta è migliore del accettata, perché permette cursore insieme a qualche posizione nel testo inserito, ma, come una direttiva hanno proprio ambito - Propongo di cambiare titolo focusedElement variabile isElementFocused e conservare non vera o falsa
Vladimir Gordienko

2
Ottengo TypeError Uncaught: undefined non è una funzione su "this" per .select (); e sì jQuery 1.9.1 è incluso.
Robbie Smith

@RobbieSmith Sono in ritardo di 3 anni, ma cambia tutte le istanze di thisto element[0]e dovrebbe funzionare. Consiglio anche di passare clicka in focusmodo che il testo venga selezionato se l'utente inserisce il tab nell'input invece di fare clic su di esso.
Lex

40

Questa è una vecchia risposta, per Angular 1.x

Il modo migliore per farlo è usare la ng-clickdirettiva incorporata:

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

MODIFICARE:

Come JoshMB ha gentilmente ricordato; non è più consentito fare riferimento ai nodi DOM in Angular 1.2+. Quindi, sono passato $event.target.select()al controller:

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

Quindi nel tuo controller:

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

Ecco un esempio di violino .


2
Per quanto ne so, questo non è più supportato. Angular genera un errore: "Il riferimento ai nodi DOM nelle espressioni angolari non è consentito!". Vedi questo thread per maggiori informazioni: groups.google.com/forum/#!topic/angular/bsTbZ86WAY4 . Tuttavia, l'approccio direttiva funziona bene.
JoshMB

Hai ragione. Questo è il caso di Angular 1.2+. Aggiornerò la risposta.
Onur Yıldırım

2
Le modifiche al DOM dovrebbero essere fatte nella direttiva, o no?
Piioo

Per qualche motivo le altre soluzioni non hanno funzionato per me, ma questo ha funzionato. Penso che il problema fosse che avevo già una direttiva sull'elemento a cui stavo aggiungendo questo evento clic.
Precastica

Scherzi a parte, anche onTextClick ($ event) sta generando l'errore ora. A parte la natura poco intuitiva di questa bestia, quanto ci costa questo inconveniente in termini di prestazioni?
jcalfee314

15

Nessuna delle soluzioni proposte ha funzionato bene per me. Dopo una rapida ricerca mi è venuto in mente questo:

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

  }

});

È un mix di diverse soluzioni proposte, ma funziona sia su click che su focus (si pensi all'autofocus) e consente la selezione manuale del valore parziale in ingresso.


1
Errore di sintassi corretto: last}); sostituito da: } }; });
Blackfire

Questo funziona per input type = "number", il che è fantastico! Grazie
Louis

Ehi, questo funziona per Ionic su Android, ma non su iOS ... qualche idea perché? Grazie
Louis

2
Sembra che tu abbia dimenticato del codice quando lo hai adattato da onClick ... qual è il punto focusedElement?
Langdon

12

Per me, ng-click non aveva senso, perché non si poteva riposizionare il cursore senza selezionare di nuovo tutto il testo, ho trovato che questo era fastidioso. Quindi è meglio usare ng-focus, perché il testo è selezionato solo se l'input non era focalizzato, se fai di nuovo clic per riposizionare il cursore, il testo viene deselezionato, come previsto, e puoi scrivere in mezzo.

Ho trovato questo approccio come il comportamento UX previsto.

Usa ng-focus

Opzione 1: codice separato

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

e nel controller

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

Opzione 2: in alternativa puoi unire il codice sopra in questo "one-liner" (non l'ho testato ma dovrebbe funzionare)

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

Semplice e funziona. Ciò consente anche il posizionamento del cursore all'interno del testo selezionato, come discusso sopra.
pistol-pete

7

In angular 2, questo ha funzionato per me, sia in Chrome che in Firefox:

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

6

La risposta accettata sta usando l'evento click, tuttavia se usi l'evento focus, solo il primo clic attiverà l'evento e si attiva anche quando viene utilizzato un altro metodo per concentrarsi sull'input (come premere tab o chiamare il focus nel codice).

Ciò inoltre rende superfluo controllare se l'elemento è già focalizzato come suggerisce la risposta di Tamlyn.

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

In Firefox 38.0.5 fare clic al centro del testo per prima cosa seleziona tutto, ma poi rimuove la selezione, quindi questo non funzionerà.
user1338062

1
Questo probabilmente non funzionerà mai in modo coerente senza ritardi this.select.
Langdon

6

Non sono necessarie direttive, basta aggiungere onfocus="this.select()"javascript nativo all'elemento di input o all'area di testo.


1
come mai così tante persone escogitano tutte queste risposte complesse, quando il modo più semplice è qui: D Grazie Adam
SwissCoder

0

Versione modificata che ha funzionato per me. Il primo clic seleziona il testo, il secondo clic sullo stesso elemento deseleziona il testo

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

Il modo più semplice per selezionare tutto il testo su clic o focus o tab è !!!:

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

...

inputFocused(event: any){
    event.target.select()
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.