Giriş odağında metin seçin


121

Metin girdim var. Giriş odak aldığında, girişin içindeki metni seçmek istiyorum.

JQuery ile bunu şu şekilde yapardım:

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

Açısal yolu denemek ve bulmak için etrafı araştırdım, ancak bulduğum çoğu örnek, bir değişiklik için modal bir özelliği izleyen bir direktifle ilgileniyor. Odak alan bir girdiyi izleyen bir yönergeye ihtiyacım olduğunu varsayıyorum. Bunu nasıl yaparım?


'Açısal bir yol' bulmak istediğinizi anlıyorum, ancak bunu yapmamanız için herhangi bir neden var <input type="text" value="test" onclick="this.select()" />mı?
Josef P.

Yanıtlar:


216

Bunu Angular'da yapmanın yolu, sizin için otomatik seçim yapan özel bir yönerge oluşturmaktır.

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

Yönergeyi şu şekilde uygulayın:

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

View demo

Güncelleme1 : jQuery bağımlılığı kaldırıldı.

Güncelleme2 : Öznitelik olarak kısıtlayın.

Güncelleme3 : Mobil Safari'de çalışır. Metnin bir bölümünü seçmeye izin verir (IE> 8 gerektirir).


10
Bunu jquery olmadan yapmak istiyorsanız, element.click öğesini element.bind ('click', function () {...} ve element.select () öğesini [0] .select ()
jack

3
Güzel ve zarif. restrict: 'A'Bu direktif mevcut bir öğenin davranışını genişletmeyi amaçladığından, yönergenin öznitelik olarak uygulanmasını (bir nesnenin değişmezi ve ayarını döndürerek) açıkça sınırlandırırım .
Eliran Malka

@Martin, kullanıcı tıklamadan sayfa açarken bunu nasıl yapacağına dair bir fikrin var mı? Sorun şu ki, varsayılan değer, benim selectOnLoadyönerge linkimden () önce başka bir denetleyicide ayarlanmış . Ancak link () içinde, kapsam zaten doldurulmuş olmasına rağmen, DOM öğesi henüz $ kapsam ile senkronize edilmedi, bu nedenle select () 'i çağırdığımda öğe hala boş ve hiçbir şey seçilmedi. Bulduğum çözülmenin tek yolu $ zaman aşımı, ancak bunun yeni bir Açısal sürümle çalışmayı bırakabileceğini hissediyorum.
Dzmitry Lazerka

bu masaüstü / android'de iyi çalışıyor ancak ipad'i denediğimde çalışmıyor gibi görünüyor. Buralarda bilinen bir iş var mı?
ak85


44

Burada, kullanıcı imleci giriş kutusuna yerleştirmek için tıkladığında metnin yeniden seçilmesini önleyen gelişmiş bir yönerge.

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
Bir yönerge olarak kendi kapsamı var, girilen metindeki bazı pozisyona set imleç izin çünkü bu cevap, daha iyi kabul daha olduğunu düşünüyorum, ama - ı adlandırmak teklif focusedElement değişkeni isElementFocused ve mağaza var gerçek veya sahte
Vladimir Gordienko

2
Yakalanmamış TypeError alıyorum: tanımsız, .select () için "this" üzerinde bir işlev değil; ve evet jQuery 1.9.1 dahildir.
Robbie Smith

@RobbieSmith 3 yıl geciktim, ancak tüm örneklerini olarak thisdeğiştirin element[0]ve işe yaramalı . Ayrıca , kullanıcı girişe tıklamak yerine sekme girerse metnin seçilmesi clickiçin olarak değiştirmenizi öneririm focus.
Lex

40

Bu, Angular 1.x için eski bir cevaptır.

Bunu yapmanın daha iyi yolu, ng-clickyerleşik yönergeyi kullanmaktır:

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

DÜZENLE:

Şöyle JoshMB nazik hatırlattığı; Angular 1.2+ sürümünde DOM düğümlerine başvurmaya artık izin verilmiyor. Yani, $event.target.select()denetleyiciye geçtim :

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

Sonra kontrol cihazınızda:

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

İşte bir örnek keman .


2
Anladığım kadarıyla bu artık desteklenmiyor. Angular bir hata verir: "Angular ifadelerde DOM düğümlerine başvurmaya izin verilmez!". Daha fazla bilgi için bu ileti dizisine bakın: groups.google.com/forum/#!topic/angular/bsTbZ86WAY4 . Yönlendirici yaklaşım yine de iyi çalışıyor.
JoshMB

Haklısın. Angular 1.2+ için durum budur. Cevabı güncelleyeceğim.
Onur Yıldırım

2
DOM değişiklikleri direktifte yapılmalı mı yapılmamalı mı?
Piioo

Nedense diğer çözümler benim için işe yaramadı ama bu işe yaradı. Sanırım sorun, bu tıklama olayını eklediğim öğeyle ilgili zaten bir yönergeye sahip olmamdı.
Precastic

Cidden, onTextClick ($ olayı) bile şu anda hatayı atıyor. Bu canavarın sezgisel olmayan doğası bir yana, bu rahatsızlık performans açısından bize ne kadara mal oluyor?
jcalfee314

15

Önerilen çözümlerin hiçbiri benim için iyi sonuç vermedi. Hızlı bir araştırmadan sonra şunu buldum:

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

  }

});

Önerilen birkaç çözümün bir karışımıdır, ancak hem tıklama hem de odak üzerinde çalışır (otomatik odaklamayı düşünün) ve girdideki kısmi değerin manuel olarak seçilmesine izin verir.


1
Sözdizimi hatası düzeltildi: last}); ile değiştirin:}}; });
Blackfire

Bu, input type = "number" için çalışıyor, bu harika! Teşekkürler
Louis

Hey, bu Android'de Ionic için çalışıyor, ancak iOS'ta değil ... neden? Teşekkürler
Louis

2
Görünüşe göre onClick'ten uyarlarken geride bir kod bırakmışsınız ... ne anlamı var focusedElement?
Langdon

12

Benim için ng-tıklamanın bir anlamı yoktu, çünkü tüm metni tekrar seçmeden imleci asla yeniden konumlandıramazsınız, bunun can sıkıcı olduğunu gördüm. Bu durumda ng-odak kullanmak daha iyidir, çünkü metin yalnızca girişe odaklanılmamışsa seçilir, imleci yeniden konumlandırmak için tekrar tıklarsanız, beklendiği gibi metin yalnızca seçimi kaldırır ve aralarına yazabilirsiniz.

Bu yaklaşımı beklenen UX davranışı olarak buldum.

Kullan ng odaklama

Seçenek 1: ayrı kod

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

ve kontrolörde

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

Seçenek 2: Alternatif olarak, yukarıdaki kodu bu "tek satırlık" olarak birleştirebilirsiniz (bunu test etmedim ama işe yaramalı)

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

Basit ve işe yarıyor. Bu aynı zamanda yukarıda tartışıldığı gibi imlecinizin seçilen metin içinde konumlandırılmasına da izin verir.
pistol-pete

7

Açısal 2'de bu, hem Chrome hem de Firefox'ta benim için çalıştı:

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

6

Kabul edilen cevap tıklama olayını kullanmaktır ancak odak olayını kullanırsanız, yalnızca 1. tıklama olayı tetikler ve aynı zamanda girdiye odaklanmak için başka bir yöntem kullanıldığında (sekmeye basmak veya kodda odağı çağırmak gibi) tetiklenir.

Bu aynı zamanda, Tamlyn'in cevabının da önerdiği gibi, öğenin zaten odaklanmış olup olmadığını kontrol etmeyi gereksiz kılar.

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

Firefox 38.0.5'te, metnin ortasına tıklamak önce tümünü seçer, sonra seçimi kaldırır, böylece bu işe yaramaz.
user1338062

1
Bu muhtemelen hiç gecikmeden tutarlı bir şekilde çalışmayacaktır this.select.
Langdon

6

Yönerge gerekmez, yalnızca onfocus="this.select()"giriş öğesine veya metin alanına yerel javascript ekleyin .


1
en kolay yol buradayken nasıl bu kadar çok insan tüm bu karmaşık cevapları
buluyor

0

Benim için çalışan değiştirilmiş sürüm. İlk tıklama metni seçer, aynı öğeye ikinci tıklama metnin seçimini kaldırır

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

Tıklama veya odak veya sekmedeki tüm metni seçmenin en kolay yolu !!!:

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

...

inputFocused(event: any){
    event.target.select()
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.