เลือกข้อความที่โฟกัสอินพุต


121

ฉันมีการป้อนข้อความ เมื่ออินพุตได้รับโฟกัสฉันต้องการเลือกข้อความภายในอินพุต

ด้วย jQuery ฉันจะทำเช่นนี้:

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

ฉันค้นหาไปรอบ ๆ เพื่อลองหาวิธีเชิงมุม แต่ตัวอย่างส่วนใหญ่ที่ฉันพบคือการจัดการกับคำสั่งที่กำลังดูคุณสมบัติโมดอลสำหรับการเปลี่ยนแปลง ฉันสมมติว่าฉันต้องการคำสั่งที่คอยดูอินพุตที่ได้รับโฟกัส ฉันจะทำอย่างไร


ฉันเข้าใจว่าคุณต้องการหา 'วิธีเชิงมุม' แต่มีเหตุผลอะไรที่คุณจะไม่ทำ<input type="text" value="test" onclick="this.select()" />?
Josef P.

คำตอบ:


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') เป็นจุดมุ่งหมายของคำสั่งนี้สำหรับการขยายการทำงานขององค์ประกอบที่มีอยู่
Eliran Malka

@Martin มีความคิดอย่างไรในการเปิดหน้าโดยไม่ต้องคลิกผู้ใช้? ปัญหาคือค่าเริ่มต้นถูกตั้งค่าในคอนโทรลเลอร์อื่นก่อนselectOnLoadลิงก์คำสั่งของฉัน() แต่ใน link () แม้ว่าจะมีการเติมขอบเขตแล้ว แต่องค์ประกอบ DOM ยังไม่ได้ซิงค์กับ $ ขอบเขตดังนั้นเมื่อฉันเรียกใช้ select () องค์ประกอบจะยังคงว่างเปล่าและไม่มีการเลือกอะไรเลย วิธีเดียวในการแก้ไขปัญหาที่ฉันพบคือ $ timeout แต่ฉันรู้สึกว่าสามารถหยุดทำงานกับ Angular เวอร์ชันใหม่ได้
Dzmitry Lazerka

มันทำงานได้ดีบนเดสก์ท็อป / Android แต่เมื่อฉันลองบน ipad ดูเหมือนจะไม่ทำงาน มีงานที่รู้จักอยู่แถวนี้ไหม?
ak85


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 ไม่ใช่ฟังก์ชันใน "this" สำหรับ .select (); และใช่ jQuery 1.9.1 รวมอยู่ด้วย
Robbie Smith

@RobbieSmith ฉัน 3 ปีปลาย แต่เปลี่ยนทุกกรณีthisไปelement[0]และมันควรจะทำงาน ฉันขอแนะนำให้เปลี่ยนclickเป็นfocusเพื่อให้ข้อความนั้นถูกเลือกหากผู้ใช้แท็บเข้าไปในอินพุตแทนที่จะคลิกเข้าไป
Lex

40

นี่เป็นคำตอบเก่าสำหรับ Angular 1.x

วิธีที่ดีกว่าคือใช้ng-clickคำสั่งในตัว:

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

แก้ไข:

ตามที่JoshMBได้เตือนไว้อย่างกรุณา; ไม่อนุญาตให้อ้างถึงโหนด DOM ใน Angular 1.2+ อีกต่อไป ดังนั้นฉันจึงย้าย$event.target.select()เข้าไปในคอนโทรลเลอร์:

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

จากนั้นในคอนโทรลเลอร์ของคุณ:

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

นี่คือไวโอลินตัวอย่างเช่น


2
เท่าที่ฉันสามารถบอกได้ว่าสิ่งนี้ไม่ได้รับการสนับสนุนอีกต่อไป Angular แสดงข้อผิดพลาด: "ไม่อนุญาตให้อ้างอิงโหนด DOM ในนิพจน์เชิงมุม!" ดูหัวข้อนี้สำหรับข้อมูลเพิ่มเติม: groups.google.com/forum/#!topic/angular/bsTbZ86WAY4 อย่างไรก็ตามแนวทางคำสั่งใช้งานได้ดี
JoshMB

คุณถูก. นี่เป็นกรณีของ Angular 1.2+ ฉันจะอัปเดตคำตอบ
Onur Yıldırım

2
การเปลี่ยนแปลง DOM ควรทำในคำสั่งหรือไม่?
Piioo

ด้วยเหตุผลบางประการวิธีแก้ปัญหาอื่น ๆ ไม่ได้ผลสำหรับฉัน แต่สิ่งนี้ทำได้ ฉันคิดว่าปัญหาคือฉันมีคำสั่งเกี่ยวกับองค์ประกอบที่ฉันกำลังเพิ่มเหตุการณ์คลิกนี้อยู่แล้ว
Precastic

อย่างจริงจังแม้แต่ 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

อันนี้ใช้ได้กับ input type = "number" ซึ่งเยี่ยมมาก! ขอบคุณ
หลุยส์

นี่ใช้ได้กับ Ionic ใน Android แต่ไม่ใช่ใน iOS ... มีความคิดอย่างไร ขอบคุณ
Louis

2
ดูเหมือนว่าคุณจะทิ้งโค้ดบางอย่างไว้ข้างหลังเมื่อคุณดัดแปลงจาก onClick ... ประเด็นfocusedElementคืออะไร?
Langdon

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:เป็นอีกทางเลือกหนึ่งที่คุณสามารถรวมโค้ดด้านบนลงใน "one-liner" นี้ได้ (ฉันไม่ได้ทดสอบ แต่ควรใช้งานได้)

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

เรียบง่ายและใช้งานได้จริง นอกจากนี้ยังช่วยให้สามารถวางตำแหน่งเคอร์เซอร์ของคุณภายในข้อความที่เลือกได้ตามที่กล่าวไว้ข้างต้น
ปืนพก - พีท

7

ในเชิงมุม 2 สิ่งนี้ใช้ได้กับฉันทั้งใน Chrome และ Firefox:

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

6

คำตอบที่ยอมรับคือการใช้เหตุการณ์การคลิกอย่างไรก็ตามหากคุณใช้เหตุการณ์โฟกัสเพียงคลิกครั้งแรกเท่านั้นที่จะเริ่มเหตุการณ์และยังเริ่มทำงานเมื่อใช้วิธีอื่นบางอย่างเพื่อโฟกัสที่ข้อมูลเข้า (เช่นการกดปุ่มแท็บหรือการเรียกโฟกัสในโค้ด)

นอกจากนี้ยังทำให้ไม่จำเป็นต้องตรวจสอบว่าองค์ประกอบนั้นโฟกัสอยู่แล้วตามที่คำตอบของ Tamlyn แนะนำหรือไม่

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

ใน Firefox 38.0.5 ให้คลิกตรงกลางข้อความก่อนจะเลือกทั้งหมด แต่จะลบส่วนที่เลือกออกดังนั้นจะไม่ได้ผล
user1338062

1
สิ่งนี้อาจจะไม่ได้ผลอย่างสม่ำเสมอโดยไม่รอthis.selectช้า
Langdon

6

ไม่จำเป็นต้องมีคำสั่งเพียงเพิ่มonfocus="this.select()"จาวาสคริปต์ดั้งเดิมในองค์ประกอบอินพุตหรือพื้นที่ข้อความ


1
ทำไมคนจำนวนมากถึงคิดคำตอบที่ซับซ้อนเหล่านี้เมื่อวิธีที่ง่ายที่สุดอยู่ที่นี่: D ขอบคุณ Adam
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
        });
    }
}

})


0

วิธีที่ง่ายที่สุดในการเลือกข้อความทั้งหมดเมื่อคลิกหรือโฟกัสหรือแท็บคือ !!!:

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

...

inputFocused(event: any){
    event.target.select()
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.