Chọn văn bản trên tiêu điểm đầu vào


121

Tôi có một đầu vào văn bản. Khi đầu vào nhận được tiêu điểm, tôi muốn chọn văn bản bên trong của đầu vào.

Với jQuery, tôi sẽ làm theo cách này:

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

Tôi đã tìm kiếm xung quanh để thử và tìm cách Angular nhưng hầu hết các ví dụ mà tôi tìm thấy đang xử lý một chỉ thị đang xem thuộc tính phương thức để thay đổi. Tôi giả định rằng tôi cần một chỉ thị đang theo dõi đầu vào nhận được tiêu điểm. Tôi sẽ làm điều đó như thế nào?


Tôi hiểu rằng bạn muốn tìm một 'Angular way', tuy nhiên, có lý do gì mà bạn không làm <input type="text" value="test" onclick="this.select()" />?
Josef P.

Câu trả lời:


216

Cách thực hiện điều này trong Angular là tạo một chỉ thị tùy chỉnh để tự động chọn cho bạn.

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

Áp dụng chỉ thị như sau:

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

View demo

Cập nhật1 : Đã loại bỏ phụ thuộc jQuery.

Update2 : Hạn chế dưới dạng thuộc tính.

Cập nhật 3 : Hoạt động trong Safari di động. Cho phép chọn một phần văn bản (yêu cầu IE> 8).


10
Nếu bạn muốn thực hiện việc này mà không cần jquery, hãy thay đổi element.click thành element.bind ('click', function () {...} và element.select () thành element [0] .select ()
jack

3
Đẹp và thanh lịch. Tôi cũng sẽ hạn chế rõ ràng chỉ thị được áp dụng dưới dạng thuộc tính (bằng cách trả về một đối tượng theo nghĩa đen và cài đặt restrict: 'A'), vì chỉ thị này nhằm mục đích mở rộng hành vi của một phần tử hiện có .
Eliran Malka

@Martin có ý kiến ​​gì về cách thực hiện điều đó trên trang mở mà không cần người dùng nhấp chuột không? Vấn đề là giá trị mặc định được đặt trong một bộ điều khiển khác trước selectOnLoadliên kết chỉ thị của tôi (). Nhưng trong liên kết (), mặc dù phạm vi đã được điền, phần tử DOM vẫn chưa được đồng bộ hóa với $ scope, vì vậy khi tôi gọi select (), phần tử vẫn trống và không có gì được chọn. Cách duy nhất để giải quyết vấn đề mà tôi tìm thấy, là $ timeout, nhưng tôi cảm thấy điều đó có thể ngừng hoạt động với một số phiên bản Angular mới.
Dzmitry Lazerka

điều này hoạt động tốt trên máy tính để bàn / Android nhưng khi tôi thử trên ipad thì nó dường như không hoạt động. Có một công việc được biết đến xung quanh đây?
ak85,


44

Đây là một chỉ thị nâng cao giúp tránh chọn lại văn bản khi người dùng nhấp để định vị con trỏ trong hộp nhập liệu.

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
Tôi nghĩ rằng câu trả lời này là tốt hơn so với chấp nhận, bởi vì nó cho phép thiết lập con trỏ đến một số vị trí trong văn bản nhập vào, nhưng, như một chỉ thị có phạm vi riêng - tôi đề nghị đổi tên focusedElement biến để isElementFocused và cửa hàng có đúng hay sai
Vladimir Gordienko

2
Tôi nhận được Uncaught TypeError: undefined không phải là một hàm trên "this" cho .select (); và có jQuery 1.9.1 được bao gồm.
Robbie Smith

@RobbieSmith Tôi đã trễ 3 năm, nhưng hãy thay đổi tất cả các trường hợp thisthành element[0]và nó sẽ hoạt động. Tôi cũng khuyên bạn nên thay đổi clickthành focusđể văn bản sẽ được chọn nếu người dùng nhấn vào mục nhập thay vì nhấp vào văn bản đó.
Lex

40

Đây là một câu trả lời cũ cho Angular 1.x

Cách tốt hơn để làm điều đó là sử dụng ng-clickchỉ thị được tích hợp sẵn:

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

BIÊN TẬP:

Như JoshMB đã vui lòng nhắc nhở; tham chiếu đến các nút DOM trong Angular 1.2+ không còn được phép. Vì vậy, tôi đã chuyển $event.target.select()sang bộ điều khiển:

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

Sau đó, trong bộ điều khiển của bạn:

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

Đây là một ví dụ fiddle .


2
Theo như tôi có thể nói, điều này không còn được hỗ trợ. Angular thông báo lỗi: "Không cho phép tham chiếu các nút DOM trong biểu thức Angular!". Xem chuỗi này để biết thêm thông tin: groups.google.com/forum/#!topic/angular/bsTbZ86WAY4 . Tuy nhiên, cách tiếp cận chỉ thị hoạt động tốt.
JoshMB

Bạn đúng. Đây là trường hợp của Angular 1.2+. Tôi sẽ cập nhật câu trả lời.
Onur Yıldırım

2
Các thay đổi DOM có nên được thực hiện trong chỉ thị hay không?
Piioo

Vì một số lý do mà các giải pháp khác không hoạt động với tôi nhưng điều này đã làm. Tôi nghĩ vấn đề là tôi đã có chỉ thị về phần tử mà tôi đang thêm sự kiện nhấp chuột này vào.
Precastic

Nghiêm túc mà nói, ngay cả onTextClick ($ event) hiện đang gặp lỗi. Ngoài bản chất không trực quan của con quái vật này, sự bất tiện này khiến chúng ta phải trả giá bao nhiêu về hiệu suất?
jcalfee314

15

Cả hai giải pháp được đề xuất đều không hoạt động tốt đối với tôi. Sau khi nghiên cứu nhanh, tôi đã nghĩ ra điều này:

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

  }

});

Đó là sự kết hợp của một số giải pháp được đề xuất, nhưng hoạt động cả khi nhấp và lấy nét (nghĩ là lấy nét tự động) và cho phép lựa chọn thủ công giá trị một phần trong đầu vào.


1
Đã sửa lỗi cú pháp: last}); thay thế bởi: } }; });
Blackfire

Cái này hoạt động cho kiểu đầu vào = "number", thật tuyệt! Cảm ơn
Louis

Này, tính năng này hoạt động với Ionic trong Android, nhưng không hoạt động với iOS ... bất kỳ ý kiến ​​nào tại sao? Cảm ơn
Louis

2
Có vẻ như bạn đã để lại một số mã khi chuyển thể nó từ onClick ... mục đích là focusedElementgì?
Langdon

12

Đối với tôi, ng-click không có ý nghĩa gì, bởi vì bạn không bao giờ có thể định vị lại con trỏ mà không chọn lại tất cả văn bản, tôi thấy điều này thật khó chịu. Sau đó, tốt hơn là sử dụng ng-focus, vì văn bản chỉ được chọn nếu đầu vào không được lấy tiêu điểm, nếu bạn nhấp lại để định vị lại con trỏ thì văn bản chỉ bỏ chọn, như mong đợi và bạn có thể viết ở giữa.

Tôi thấy cách tiếp cận này là hành vi UX được mong đợi.

Sử dụng ng-focus

Tùy chọn 1: mã riêng

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

và trong bộ điều khiển

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

Tùy chọn 2: để thay thế, bạn có thể nối mã ở trên vào "một lớp lót" này (Tôi đã không kiểm tra điều này nhưng nó sẽ hoạt động)

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

Đơn giản và nó hoạt động. Điều này cũng cho phép định vị con trỏ của bạn trong văn bản đã chọn, như đã thảo luận ở trên.
pistol-pete

7

Trong góc 2, điều này phù hợp với tôi, cả trong Chrome và Firefox:

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

6

Câu trả lời được chấp nhận là sử dụng sự kiện nhấp chuột, tuy nhiên nếu bạn sử dụng sự kiện tiêu điểm, chỉ nhấp chuột đầu tiên sẽ kích hoạt sự kiện và nó cũng kích hoạt khi một số phương pháp khác được sử dụng để tập trung vào đầu vào (như nhấn tab hoặc gọi tiêu điểm trong mã).

Điều này cũng làm cho việc kiểm tra xem yếu tố đã được tập trung hay chưa như câu trả lời của Tamlyn gợi ý là không cần thiết.

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

Trong Firefox 38.0.5, nhấp vào giữa văn bản trước tiên sẽ chọn tất cả, nhưng sau đó xóa lựa chọn, vì vậy điều này sẽ không hoạt động.
user1338062

1
Điều này có lẽ sẽ không bao giờ hoạt động ổn định mà không bị trì hoãn this.select.
Langdon

6

Không cần chỉ thị, chỉ cần thêm onfocus="this.select()"javascript gốc vào phần tử đầu vào hoặc vùng văn bản.


1
Sao

0

Phiên bản sửa đổi phù hợp với tôi. Nhấp chuột đầu tiên để chọn văn bản, nhấp chuột thứ hai vào cùng một phần tử bỏ chọn văn bản

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

Cách dễ nhất để chọn tất cả văn bản trên nhấp chuột hoặc tiêu điểm hoặc tab, là !!!:

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

...

inputFocused(event: any){
    event.target.select()
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.