选择输入焦点上的文本


121

我有文字输入。当输入获得焦点时,我想选择输入内的文本。

使用jQuery,我可以这样:

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

我四处搜寻以尝试找到Angular方法,但是我发现的大多数示例都在处理一个指令,该指令正在监视模式属性的更改。我假设我需要一个指令来监视接收焦点的输入。我该怎么办?


我了解您想找到一种“成角度的方式”,但是,有什么理由您会不只是这样做<input type="text" value="test" onclick="this.select()" />
Josef P.

Answers:


216

在Angular中执行此操作的方法是创建一个自定义指令,该指令会为您自动选择。

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

应用如下指令:

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

View demo

Update1:删除了jQuery依赖项。

Update2:限制为属性。

Update3:在移动Safari中工作。允许选择部分文本(要求IE> 8)。


10
如果要在不使用jquery的情况下执行此操作,请将element.click更改为element.bind('click',function(){...}和element.select()更改为element [0] .select()
杰克

3
尼斯和优雅。我还将明确限制将指令用作属性(通过返回对象文字和设置restrict: 'A'),因为该指令旨在扩展现有元素的行为
伊莱兰·马尔卡

@Martin知道如何在打开页面时进行操作,而无需用户单击?问题是我的selectOnLoad指令link()之前在另一个控制器中设置了默认值。但是在link()中,尽管作用域已被填充,但元素DOM尚未与$ scope同步,因此当我调用select()时,元素仍然为空且未选择任何内容。我发现的唯一解决方法是$ timeout,但我认为这可能会停止使用某些新的Angular版本。
Dzmitry Lazerka

这在台式机/ Android上很好用,但是当我在ipad上尝试时似乎不起作用。这附近有个知名的作品吗?
2015年


44

这是一个增强的指令,可避免在用户单击以将光标置于输入框中时重新选择文本。

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
我想这个答案是优于接受,因为它允许设置光标在输入的文本一些位置,但作为一个指令有自己的范围-我建议重命名focusedElement变量isElementFocused和存储有假的
弗拉基米尔Gordienko

2
我得到了Uncaught TypeError:undefined不是.select()的“ this”函数。是的,其中包括jQuery 1.9.1。
罗比·史密斯

@RobbieSmith我迟到了3年,但将thisto的所有实例都更改了element[0]就可以了。我还建议更改click为,focus以便在用户使用制表符输入而不是单击输入时选择文本。
Lex

40

对于Angular 1.x,这是个旧答案

更好的方法是使用ng-click内置指令:

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

编辑:

正如JoshMB所提醒的那样;不再允许在Angular 1.2+中引用DOM节点。因此,我$event.target.select()进入了控制器:

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

然后在您的控制器中:

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

这是一个小提琴例子


2
据我所知,这不再受支持。Angular引发错误:“不允许在Angular表达式中引用DOM节点!”。有关更多信息,请参见此线程: groups.google.com/forum/# ! topic/angular/bsTbZ86WAY4。但是,指令方法效果很好。
JoshMB

你是对的。Angular 1.2+就是这种情况。我将更新答案。
OnurYıldırım2014年

2
是否应该在指令中进行DOM更改?
Piioo 2014年

出于某种原因,其他解决方案对我不起作用,但对我却有效。我认为问题是我已经对要添加此click事件的元素进行了指令。
预制2015年

严重的是,即使onTextClick($ event)现在也会引发错误。除了这种野兽的非直觉性之外,这种不便给我们带来了多少性能损失?
jcalfee314

15

提议的解决方案都不适合我。经过快速研究,我得出了以下结论:

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

  }

});

它是提议的几种解决方案的组合,但是可以同时使用单击和聚焦(认为是自动聚焦),并且可以手动选择输入中的部分值。


1
语法错误已更正:last}); 替换为:}}; });
Blackfire

这个适用于输入type =“ number”,太好了!谢谢
路易(Louis)

嘿,这适用于Android上的Ionic,但不适用于iOS。...知道为什么吗?谢谢
路易(Louis)

2
好像您从onClick修改代码时留下了一些代码……这有什么意义focusedElement
兰登

12

对我而言,ng-click没有意义,因为您无法在不再次选择所有文本的情况下重新定位光标,我发现这很烦人。然后最好使用ng-focus,因为仅当输入未聚焦时才选择文本,如果再次单击以重新定位光标,则文本将按预期取消选择,并且可以在两者之间进行书写。

我发现这种方法是预期的UX行为。

使用ng-focus

选项1:单独的代码

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

并在控制器中

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

选项2:作为替代方案,您可以将上面的代码加入此“单一代码”中(我没有对此进行测试,但应该可以使用)

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

简单并且有效。如上所述,这还允许将光标定位在所选文本内。
手枪-皮特

7

在角度2中,这对我都有效,在Chrome和Firefox中均如此:

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

6

可接受的答案是使用click事件,但是,如果您使用focus事件,则只有第1次单击会触发该事件,并且在使用其他一些方法来关注输入时也会触发该事件(例如单击选项卡或在代码中调用focus)。

这也使得不必像Tamlyn的答案所建议的那样检查元素是否已经集中。

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

在Firefox 38.0.5中,首先单击文本中间的所有内容,然后将其删除,所以这将不起作用。
user1338062 2015年

1
这可能永远无法持续工作而没有拖延this.select
兰登

6

无需任何指令,只需将onfocus="this.select()"本机javascript 添加到输入元素或文本区域即可。


1
当最简单的方法在这里时,为什么会有这么多人提出所有这些复杂的答案:D谢谢亚当
SwissCoder

0

对我有用的修改版。第一次单击选择文本,第二次单击同一元素取消选择文本

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

})

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.