<इनपुट> तत्व पर ध्यान केंद्रित करें


108

मैं Angular 5 के साथ एक फ्रंट-एंड एप्लिकेशन काम कर रहा हूं, और मुझे एक खोज बॉक्स छिपाना होगा, लेकिन एक बटन पर क्लिक करने पर, खोज बॉक्स प्रदर्शित और केंद्रित होना चाहिए।

मैंने निर्देशन के साथ StackOverflow पर पाए जाने वाले कुछ तरीकों की कोशिश की है, लेकिन सफल नहीं हो सकता।

यहाँ नमूना कोड है:

@Component({
   selector: 'my-app',
   template: `
    <div>
    <h2>Hello</h2>
    </div>
    <button (click) ="showSearch()">Show Search</button>
    <p></p>
    <form>
      <div >
        <input *ngIf="show" #search type="text"  />            
      </div>
    </form>
    `,
  })
  export class App implements AfterViewInit {
  @ViewChild('search') searchElement: ElementRef;

  show: false;
  name:string;
  constructor() {    
  }

  showSearch(){
    this.show = !this.show;    
    this.searchElement.nativeElement.focus();
    alert("focus");
  }

  ngAfterViewInit() {
    this.firstNameElement.nativeElement.focus();
  }

खोज बॉक्स को फ़ोकस करने के लिए सेट नहीं किया गया है।

मैं उसे कैसे कर सकता हूँ?

जवाबों:


128

इस तरह शो सर्च मेथड को संशोधित करें

showSearch(){
  this.show = !this.show;  
  setTimeout(()=>{ // this will make the execution after the above boolean has changed
    this.searchElement.nativeElement.focus();
  },0);  
}

15
हमें सेटटाइमआउट का उपयोग करने की आवश्यकता क्यों है? क्या बूलियन सिंक्रोनस का परिवर्तन नहीं है?
आंद्रेई रोजू

6
जोनज के साथ वह गड़बड़ नहीं है?
लॉफोटॉग

1
@AndreiRosu, इसके बिना मुझे एक त्रुटि मिल रही थी क्योंकि परिवर्तनों का प्रतिपादन नहीं किया गया था
इस्लाम Q.

13
यह काम करता है, लेकिन स्पष्ट विवरण के बिना यह जादू है। जादू अक्सर टूटता है।
जॉन व्हाइट

1
मैं एक पैनल के अंदर अपने तत्व पर ध्यान केंद्रित करने की कोशिश कर रहा था जब पैनल खोला गया था, तो 0 टाइमआउट मेरे लिए काम नहीं करता था, लेकिन यह किया:setTimeout(() => { this.searchElement.nativeElement.focus() }, 100)
tclark333

41

आपको इसके लिए html ऑटोफोकस का उपयोग करना चाहिए :

<input *ngIf="show" #search type="text" autofocus /> 

नोट: यदि आपका कंपोनेंट कायम है और पुन: उपयोग किया जाता है तो यह केवल पहली बार ऑटोफोकस होगा जब टुकड़ा जुड़ा हुआ है। यह एक वैश्विक डोम श्रोता होने से दूर हो सकता है जो संलग्न होने पर एक डोम टुकड़े के अंदर ऑटोफोकस विशेषता की जांच करता है और फिर इसे पुन: लागू करता है या जावास्क्रिप्ट के माध्यम से फ़ोकस करता है।


46
यह केवल प्रत्येक पृष्ठ को एक बार ताज़ा करने पर काम करेगा, कई बार नहीं।
मोरित्ज़ग

23

यह निर्देश तुरंत प्रदर्शित होने के साथ ही तत्व के किसी भी पाठ पर ध्यान केंद्रित करेगा और उसका चयन करेगा। इसके लिए कुछ मामलों में सेटटाइमआउट की आवश्यकता हो सकती है, इसका अधिक परीक्षण नहीं किया गया है।

import { Directive, ElementRef, OnInit } from '@angular/core';

@Directive({
  selector: '[appPrefixFocusAndSelect]',
})
export class FocusOnShowDirective implements OnInit {

  constructor(private el: ElementRef) {
    if (!el.nativeElement['focus']) {
      throw new Error('Element does not accept focus.');
    }
  }

  ngOnInit(): void {
    const input: HTMLInputElement = this.el.nativeElement as HTMLInputElement;
    input.focus();
    input.select();
  }
}

और HTML में:

 <mat-form-field>
     <input matInput type="text" appPrefixFocusAndSelect [value]="'etc'">
 </mat-form-field>

धन्यवाद, यह केवल एक ही संलयन है जिसने http अनुरोध पर प्रतीक्षा करने के मामले में मेरे लिए काम किया है
अब्देलहालिम फेलग्यू शेब्रा

1
मुझे यह उत्तर स्वीकृत उत्तर की तुलना में अधिक उपयोगी लगता है। यह कोड पुन: उपयोग के मामले में क्लीनर है, और अधिक कोणीय-केंद्रित है।
derekbaker783

इसके अलावा मॉड्यूल की घोषणाओं में निर्देश जोड़ना मत भूलना।
एलिजा डॉलिन

11

मैं इस पर (कोणीय 7 समाधान) में जा रहा हूँ

input [appFocus]="focus"....
import {AfterViewInit, Directive, ElementRef, Input,} from '@angular/core';

@Directive({
  selector: 'input[appFocus]',
})
export class FocusDirective implements AfterViewInit {

  @Input('appFocus')
  private focused: boolean = false;

  constructor(public element: ElementRef<HTMLElement>) {
  }

  ngAfterViewInit(): void {
    // ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.
    if (this.focused) {
      setTimeout(() => this.element.nativeElement.focus(), 0);
    }
  }
}


9

यह बिना सेट टाइमआउट के i Angular 8 काम कर रहा है:

import {AfterContentChecked, Directive, ElementRef} from '@angular/core';

@Directive({
  selector: 'input[inputAutoFocus]'
})
export class InputFocusDirective implements AfterContentChecked {
  constructor(private element: ElementRef<HTMLInputElement>) {}

  ngAfterContentChecked(): void {
    this.element.nativeElement.focus();
  }
}

स्पष्टीकरण: ठीक है इसलिए यह काम करता है: परिवर्तन का पता लगाना। यह एक ही कारण है कि setTimout काम करता है, लेकिन जब Angular में एक setTimeout चलाते हैं तो यह Zone.js को बायपास कर देगा और सभी चेक को फिर से रन करेगा, और यह तब काम करता है जब सेट टाइमआउट पूरा हो जाता है। सही जीवन चक्र हुक (AfterContentChecked) के साथ एक ही परिणाम तक पहुंचा जा सकता है, लेकिन अतिरिक्त चक्र नहीं चलाया जाएगा कि लाभ के साथ। सभी परिवर्तनों की जांच और पारित होने पर फ़ंक्शन आग जाएगा, और हुक के बाद चलता है AfterContentInit और DoCheck। अगर मैं यहाँ गलत हूँ तो कृपया मुझे सुधारें

Https://angular.io/guide/lifecycle-hooks पर एक से अधिक जीवनचक्र और परिवर्तन का पता लगाने

अद्यतन : मुझे यह करने के लिए एक और भी बेहतर तरीका मिल गया है अगर एक कोणीय सामग्री CDK, a11y-package का उपयोग किया जाता है। मॉड्यूल में पहला आयात A11yModule उस घटक की घोषणा करने के लिए जिसमें आपके पास इनपुट-फ़ील्ड है। उसके बाद cdkTrapFocus और cdkTrapFocusAutoCapture निर्देशों का उपयोग करें और HTML में इस तरह का उपयोग करें और इनपुट पर इनपुट सेट करें:

<div class="dropdown" cdkTrapFocus cdkTrapFocusAutoCapture>
    <input type="text tabIndex="0">
</div>

हमारे पास पोजिशनिंग और जवाबदेही के बारे में हमारे ड्रॉपडाउन के साथ कुछ मुद्दे थे और इसके बजाय cdk से OverlayModule का उपयोग करना शुरू किया, और A11yModule का उपयोग करने वाला यह तरीका त्रुटिपूर्ण काम करता है।


हाय ... मैं cdkTrapFocusAutoCaptureविशेषता की कोशिश नहीं करता , लेकिन मैंने आपका पहला उदाहरण अपने कोड में बदल दिया। अज्ञात कारणों से (मेरे लिए) यह AfterContentChecked जीवन चक्र हुक के साथ काम नहीं करता था, लेकिन केवल OnInit के साथ। AfterContentChecked के साथ कणक में मैं एक ही रूप में उस निर्देश के बिना किसी अन्य इनपुट पर फ़ोकस और मूव (माउस या कीबोर्ड के साथ) नहीं बदल सकता।
टिमचेयर

@timhecker हाँ, जब हमने cdk ओवरले में अपने घटकों को माइग्रेट किया है तो एक अनजाने मुद्दे का सामना करना पड़ा (स्थिति के लिए एक ओवरले के बजाय बस css का उपयोग करते समय यह काम किया)। यह इनपुट पर अनिश्चित काल तक केंद्रित रहा जब निर्देश का उपयोग करने वाला एक घटक दिखाई दे रहा था। केवल समाधान मैंने पाया कि अद्यतन में वर्णित सीडीके निर्देशों का उपयोग करना था।
SNDVLL

7

HTML में ही कोणीय में, आप एक बटन के क्लिक पर इनपुट पर ध्यान केंद्रित कर सकते हैं।

<button (click)="myInput.focus()">Click Me</button>

<input #myInput></input>

यह उत्तर HTML में प्रोग्रामेटिकली किसी अन्य तत्व का चयन करने का एक सरल तरीका दिखाता है, जो कि मैं देख रहा था (सभी "प्रारंभिक फोकस" के उत्तर इस बात को हल नहीं करते हैं कि फोकस बदलकर किसी घटना पर प्रतिक्रिया कैसे करें) - दुर्भाग्य से, मुझे प्रतिक्रिया करने की आवश्यकता है एक mat-select selectionChangedघटना जो अन्य UI सामान से पहले होती है, इसलिए उस बिंदु पर ध्यान केंद्रित करने से काम नहीं चला। इसके बजाय मुझे एक विधि लिखनी थी setFocus(el:HTMLElement):void { setTimeout(()=>el.focus(),0); }और उसे इवेंट हैंडलर से बुलाना पड़ा <mat-select (selectionChanged)="setFocus(myInput)">:। उतना अच्छा नहीं है, लेकिन सरल और अच्छी तरह से काम करता है। धन्यवाद!
Guss

मेरे लिए काम नहीं किया। मुझे ERROR TypeError मिलती है: अपरिभाषित की संपत्ति 'फ़ोकस' को नहीं पढ़ सकता
रेजा ताबा

@RezaTaba, क्या आपने 'myInput.focus' () फ़ंक्शन को कॉल किया या आपने सिर्फ 'myInput.focus' लिखा है? यह भी सुनिश्चित करें कि, आपका इनपुट एलिमेंट एक रेंडर डिव के अंदर है (* ngff त्रुटि पैदा कर सकता है, उदाहरण के लिए)
shaheer thowur

6

बूलियन को बदलने के बाद निष्पादन करने के लिए और उस समय के उपयोग से बचें जो आप कर सकते हैं:

import { ChangeDetectorRef } from '@angular/core';

constructor(private cd: ChangeDetectorRef) {}

showSearch(){
  this.show = !this.show;  
  this.cd.detectChanges();
  this.searchElement.nativeElement.focus();
}

5
मैंने इसे कोणीय 7 के साथ आज़माया, यह काम नहीं किया, टाइमआउट का उपयोग करके ठीक काम किया
rekiem87

मेरे लिए कोणीय 8 में भी काम नहीं कर रहा है, बुरा करने के लिए हमें सेटटाइमआउट पर जाना होगा
आंद्रेई चिवु


1

केवल कोणीय टेम्पलेट का उपयोग कर

<input type="text" #searchText>

<span (click)="searchText.focus()">clear</span>

"यदि आप सामग्री का उपयोग कर रहे हैं ..."
एंड्रयू कोपर

त्रुटि टाइपरोर: अपरिभाषित की संपत्ति 'फोकस' को नहीं पढ़ सकते हैं
रेजा ताबा

1

घटक का html:

<input [cdkTrapFocusAutoCapture]="show" [cdkTrapFocus]="show">

घटक का नियंत्रण:

showSearch() {
  this.show = !this.show;    
}

..और @ कोणीय / सीडीके / a11y से आयात A11yModule के बारे में मत भूलना

import { A11yModule } from '@angular/cdk/a11y'

सबसे अच्छा उपाय। धन्यवाद। अन्य समाधानों ने मुझे त्रुटि दी।
रजा तबा

1

मेरे पास एक ही परिदृश्य है, यह मेरे लिए काम करता है लेकिन आपके पास "छिपाने / दिखाने" की सुविधा नहीं है। तो शायद आप पहले यह देख सकते हैं कि क्या आपको फ़ोकस मिलता है जब आपके पास फ़ील्ड हमेशा दिखाई देता है, और फिर हल करने की कोशिश करें कि जब आप दृश्यता बदलते हैं तो काम क्यों नहीं करता है (शायद इसलिए आपको नींद या एक वादा लागू करने की आवश्यकता है)

ध्यान केंद्रित करने के लिए, यह एकमात्र परिवर्तन है जिसे आपको करने की आवश्यकता है:

आपका Html चटाई इनपुट होना चाहिए:

<input #yourControlName matInput>

अपने टीएस वर्ग में, इस तरह का संदर्भ चर खंड में (

export class blabla...
    @ViewChild("yourControlName") yourControl : ElementRef;

आपका बटन ठीक है, कॉलिंग:

  showSearch(){
       ///blabla... then finally:
       this.yourControl.nativeElement.focus();
}

और बस। आप इस समाधान को इस पोस्ट पर देख सकते हैं जो मुझे मिला, इसलिए धन्यवाद -> https://codeburst.io/focusing-on-form-elements-the-angular-way-e9a78725c04f


-1

आसान तरीका भी यही है।

let elementReference = document.querySelector('<your css, #id selector>');
    if (elementReference instanceof HTMLElement) {
        elementReference.focus();
    }

3
आप वास्तव में डोम को सीधे क्वेरी नहीं करना चाहते हैं।
रिचर्ड। डेवेनपोर्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.