Wählen Sie den Text im Eingabefokus aus

121

Ich habe eine Texteingabe. Wenn die Eingabe den Fokus erhält, möchte ich den Text innerhalb der Eingabe auswählen.

Mit jQuery würde ich es so machen:

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

Ich habe mich umgesehen, um den Angular-Weg zu finden, aber die meisten Beispiele, die ich finde, befassen sich mit einer Direktive, die eine modale Eigenschaft zur Änderung überwacht. Ich gehe davon aus, dass ich eine Direktive brauche, die nach einer Eingabe sucht, die den Fokus erhält. Wie würde ich das machen?

Billy Coover
quelle
Ich verstehe, dass Sie einen "Winkelweg" finden möchten, aber gibt es einen Grund, warum Sie dies nicht einfach tun würden <input type="text" value="test" onclick="this.select()" />?
Josef P.

Antworten:

216

In Angular können Sie dazu eine benutzerdefinierte Direktive erstellen, die die automatische Auswahl für Sie übernimmt.

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

Wenden Sie die Richtlinie folgendermaßen an:

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

View demo

Update1 : Die jQuery-Abhängigkeit wurde entfernt.

Update2 : Als Attribut einschränken .

Update3 : Funktioniert in Mobile Safari. Ermöglicht die Auswahl eines Teils des Textes (erfordert IE> 8).

Martin
quelle
10
Wenn Sie dies ohne jquery tun möchten, ändern Sie element.click in element.bind ('click', function () {...} und element.select () in element [0] .select ()
jack
3
Schön und elegant. Ich würde auch die Direktive, die als Attribut angewendet werden soll, explizit einschränken (durch Rückgabe eines Objektliteral und einer Einstellung restrict: 'A'), da diese Direktive darauf abzielt , das Verhalten eines vorhandenen Elements zu erweitern .
Eliran Malka
@Martin eine Idee, wie man das auf geöffneter Seite macht, ohne dass der Benutzer darauf klickt? Das Problem ist, dass der Standardwert in einem anderen Controller vor meiner selectOnLoadDirektive link () festgelegt ist. In link () ist das Element DOM noch nicht mit $ scope synchronisiert, obwohl der Bereich bereits ausgefüllt ist. Wenn ich also select () aufrufe, ist das Element immer noch leer und nichts ausgewählt. Die einzige Möglichkeit, das Problem zu umgehen, ist $ timeout, aber ich bin der Meinung, dass dies mit einer neuen Angular-Version nicht mehr funktionieren kann.
Dzmitry Lazerka
Dies funktioniert gut auf Desktop / Android, aber wenn ich auf iPad versuche, scheint es nicht zu funktionieren. Gibt es hier eine bekannte Arbeit?
Ak85
44

Hier ist eine erweiterte Anweisung, die verhindert, dass der Text erneut ausgewählt wird, wenn der Benutzer klickt, um den Cursor im Eingabefeld zu positionieren.

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;
            });
        }
    };
})
Tamlyn
quelle
3
Ich denke , diese Antwort ist besser als das akzeptiert, weil es in eingegebenen Text zu einem gewissen Position Satz Cursor ermöglichen, aber als Richtlinie eigene Anwendungsbereich hat - wir vorschlagen umbenennen focusedElement Variable isElementFocused und speichert es wahr oder falsch
Vladimir Gordienko
2
Ich erhalte Uncaught TypeError: undefined ist keine Funktion für "this" für .select (); und ja, jQuery 1.9.1 ist enthalten.
Robbie Smith
@RobbieSmith I 3 Jahre zu spät bin, aber alle Instanzen ändern thiszu element[0]und sollte es funktionieren. Ich empfehle auch, zu zu wechseln click, focusdamit Text ausgewählt wird, wenn der Benutzer die Eingabe mit Registerkarten anzeigt, anstatt darauf zu klicken.
Lex
40

Dies ist eine alte Antwort für Angular 1.x.

Besser ist es, die ng-clickeingebaute Direktive zu verwenden:

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

BEARBEITEN:

Wie JoshMB freundlich erinnert hat; Das Referenzieren von DOM-Knoten in Angular 1.2+ ist nicht mehr zulässig. Also bin ich $event.target.select()in den Controller eingezogen :

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

Dann in Ihrem Controller:

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

Hier ist ein Beispiel für eine Geige .

Onur Yıldırım
quelle
2
Soweit ich das beurteilen kann, wird dies nicht mehr unterstützt. Angular löst einen Fehler aus: "Das Referenzieren von DOM-Knoten in Angular-Ausdrücken ist nicht zulässig!". Weitere Informationen finden Sie in diesem Thread: groups.google.com/forum/#!topic/angular/bsTbZ86WAY4 . Der Richtlinienansatz funktioniert jedoch gut.
JoshMB
Du hast recht. Dies ist bei Angular 1.2+ der Fall. Ich werde die Antwort aktualisieren.
Onur Yıldırım
2
DOM-Änderungen sollten in der Richtlinie vorgenommen werden oder nicht?
Piioo
Aus irgendeinem Grund haben die anderen Lösungen bei mir nicht funktioniert, aber das hat funktioniert. Ich denke, das Problem war, dass ich bereits eine Direktive für das Element hatte, zu dem ich dieses Klickereignis hinzugefügt habe.
Precastic
Im Ernst, sogar der onTextClick ($ event) löst jetzt den Fehler aus. Wie viel kostet uns diese Unannehmlichkeit, abgesehen von der unintuitiven Natur dieses Tieres, an Leistung?
jcalfee314
15

Keine der vorgeschlagenen Lösungen hat für mich gut funktioniert. Nach kurzer Recherche kam ich auf Folgendes:

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

  }

});

Es ist eine Mischung aus mehreren vorgeschlagenen Lösungen, funktioniert jedoch sowohl beim Klicken als auch beim Fokussieren (denken Sie an Autofokus) und ermöglicht die manuelle Auswahl des Teilwerts in der Eingabe.

Xaralis
quelle
1
Syntaxfehler korrigiert: last}); ersetzt durch: } }; });
Blackfire
Dieser funktioniert für den Eingabetyp = "Nummer", was großartig ist! Vielen Dank
Louis
Hey, das funktioniert für Ionic in Android, aber nicht in iOS ... eine Idee warum? Vielen Dank
Louis
2
Scheint, als hätten Sie Code zurückgelassen, als Sie ihn von onClick angepasst haben ... wozu focusedElement?
Langdon
12

Für mich hatte ng-click keinen Sinn, da man den Cursor nie neu positionieren konnte, ohne den gesamten Text erneut auszuwählen. Ich fand das ärgerlich. Dann ist es besser, ng-focus zu verwenden, da der Text nur ausgewählt wird, wenn die Eingabe nicht fokussiert war. Wenn Sie erneut klicken, um den Cursor neu zu positionieren, wird die Auswahl des Texts wie erwartet einfach aufgehoben und Sie können dazwischen schreiben.

Ich fand, dass dieser Ansatz das erwartete UX-Verhalten ist.

Verwenden Sie ng-focus

Option 1: separater Code

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

und in der Steuerung

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

Option 2: Alternativ können Sie den obigen Code in diesen "Einzeiler" einfügen (ich habe dies nicht getestet, aber es sollte funktionieren).

<input type="text" ng-model="content" ng-focus="$event.target.select()" />
jperelli
quelle
Einfach und es funktioniert. Dies ermöglicht auch die Positionierung Ihres Cursors innerhalb des ausgewählten Textes, wie oben erläutert.
Pistole-Pete
7

In Winkel 2 funktionierte dies für mich, sowohl in Chrome als auch in Firefox:

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

Die akzeptierte Antwort verwendet das Klickereignis. Wenn Sie jedoch das Fokusereignis verwenden, wird das Ereignis nur durch den ersten Klick ausgelöst, und es wird auch ausgelöst, wenn eine andere Methode zum Fokussieren auf die Eingabe verwendet wird (z. B. Drücken der Registerkarte oder Aufrufen des Fokus im Code).

Dies macht es auch unnötig zu überprüfen, ob das Element bereits fokussiert ist, wie Tamlyns Antwort nahe legt.

app.directive('selectOnClick', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.on('focus', function () {
                this.select();
            });
        }
    };
});
OrangeKing89
quelle
In Firefox 38.0.5 werden durch Klicken in die Mitte des Textes zuerst alle ausgewählt, dann jedoch die Auswahl entfernt, sodass dies nicht funktioniert.
user1338062
1
Dies wird wahrscheinlich nie ohne Verzögerung konsequent funktionieren this.select.
Langdon
6

Keine Anweisungen erforderlich, fügen Sie onfocus="this.select()"dem Eingabeelement oder dem Textbereich einfach natives Javascript hinzu.

Adam Reis
quelle
1
Wie kommt es, dass so viele Menschen auf all diese komplexen Antworten kommen, wenn der einfachste Weg hier ist: D Danke Adam
SwissCoder
0

Geänderte Version, die für mich funktioniert hat. Erster Klick wählt Text aus, zweiter Klick auf dasselbe Element hebt die Auswahl von Text auf

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

})

Ola
quelle