2016-07-11 29 views

cevap

9

Basit 'odak' kullanarak yapıcı enjekte alır

this.renderer.invokeElementMethod(this.input.nativeElement, 'focus', []); 

Yönergesi

import {Directive, Input, ElementRef} from 'angular2/core'; 
@Directive({ 
    selector: '[focus]' 
}) 
class FocusDirective { 
    @Input() 
    focus:boolean; 
    constructor(@Inject(ElementRef) private element: ElementRef) {} 
    protected ngOnChanges() { 
     this.element.nativeElement.focus(); 
    } 
} 

// Usage 
@Component({ 
    selector : 'app', 
    template : ` 
     <input [focus]="inputFocused" type="text"> 
     <button (click)="moveFocus()">Move Focus</button> 
    `, 
    directives: [FocusDirective] 
}) 
export class App { 
    private inputFocused = false; 
    moveFocus() { 
     this.inputFocused = true; 
     // we need this because nothing will 
     // happens on next method call, 
     // ngOnChanges in directive is only called if value is changed, 
     // so we have to reset this value in async way, 
     // this is ugly but works 
     setTimeout(() => {this.inputFocused = false}); 
    } 
} 
+1

Küçük bir başlık. Doğrudan "nativeElement" kullanmayın. Bu web çalışanları ile tasarruf değil. – PierreDuc

+1

"Yönergeler" özelliği RC 6'da kaldırılmıştır. "FocusDirective" öğesini NgModule dekoratörünüzün beyannamelerine taşımalısınız. – cnotethegr8

+0

Aynı gereksinime sahibim fakat setTimeout'u yönerge içinde değiştirmek istiyorum, direktif içinde setTimeout kullanılarak aynı işlevsellik elde edilebilir mi? –

2

angular2 sahip bir öğenin netlik ayarı en iyi yolu var Renderer kullanarak ve eleman üzerindeki bir yöntemi çağırmak tarafından olmasıdır Angular2 yılında ngFocus direktifi yoktur. elementRef olmadan bunu yapmanın bir yolu yoktur. Böyle bir şeye

Bu sonuçlar: rendererprotected renderer : Renderer

+0

Daha iyi bir yaklaşım, öğeyi manipüle eden ve bunu bileşen sınıfında yapmayan kendi ngFocus yönergesini yazmaktır. – almog

+0

Bu kastedildi .. ve kod aynı şekilde kalıyor – PierreDuc

+0

Ama neden Angular2 ekibi yaratmadı? – almog

1

Çok daha basit bir yolu:

import { Directive, ElementRef, Renderer} from "@angular/core"; 
@Directive({ 
    selector: "[Focus]" 
}) 

export class myFocus { 
    constructor(private _el: ElementRef, private renderer: Renderer) { 
     this.renderer.invokeElementMethod(this._el.nativeElement, 'focus'); 
    } 

} 
+0

Benim için çalışmıyor çünkü görünüm gerçekten hazır olmadan önce çağrıldı çünkü – Dimanoid

+0

ngOnInit() [The Angular LifeCycle Hooks] 'a eklemelisiniz ya da o olayın ne olursa olsun ona abone olmalısınız. oldu". – ShellZero

8

Her iki varyantı denedim ancak hiçbiri basit kullanım için uygun değil. İlk olarak (@AngJobs tarafından) yönerge kullandığınız bileşende ek işleve ihtiyaç duyarsınız (set = true), 2. (@ShellZero ile) hiç çalışmıyor çünkü odaklama gerçekten görünümden önce çağrılır. Bu yüzden odak aramayı ngAfterViewInit'a taşıdım. Şimdi sadece <input focus...'u ekleyebilir ve unutabilirsiniz. Eleman, otomatik olarak init görüntülendikten sonra odaklanacaktır.

import { Directive, ElementRef, Renderer, AfterViewInit } from '@angular/core'; 
@Directive({ 
    selector: '[focus]' 
}) 

export class DmFocusDirective implements AfterViewInit { 
    constructor(private _el: ElementRef, private renderer: Renderer) { 
    } 

    ngAfterViewInit() { 
     this.renderer.invokeElementMethod(this._el.nativeElement, 'focus'); 
    } 
} 
+0

Teşekkürler - bu harika. Sınıf isminizin zorunlu olarak öneklemeye gerek duymasa da (Dm ile yaptığınız gibi). Bir önek uygulanacak anahtar bit, seçici isim değeridir. yani seçici: '[appFocus]' '. Bu, sonraki açısal versiyonlarda vb. Çarpışma olasılığını azaltır. – ne1410s

+1

Heads up: "Renderer", kullanımdan kaldırıldı ve Açısal ekip, "Renderer2" içine invokeElementMethod() 'i getirmeyi planlamıyor. https://github.com/angular/angular/issues/13818 – stealththeninja

1

Benim için çalışır, ancak konsolda hatalar var. Hata ayıklama ve aramadan sonra bu makaleyi okuyun: https://www.picnet.com.au/blogs/guido/post/2016/09/20/angular2-ng2-focus-directive/

Yalnızca kopyala yapıştır. Benim için mükemmel çalıştı.

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

@Directive({selector: '[focus]'}) 
export class FocusDirective implements AfterViewInit, DoCheck { 
    private lastVisible: boolean = false; 
    private initialised: boolean = false; 

    constructor(private el: ElementRef) { 
    } 

    ngAfterViewInit() { 
     console.log('inside FocusDirective.ngAfterViewInit()'); 
     this.initialised = true; 
     this.ngDoCheck(); 
    } 

    ngDoCheck() { 

     console.log('inside FocusDirective.ngDoCheck()'); 

     if (!this.initialised) { 
      return; 
     } 
     const visible = !!this.el.nativeElement.offsetParent; 
     if (visible && !this.lastVisible) { 
      setTimeout(() => { 
       this.el.nativeElement.focus(); 
      }, 1); 
     } 
     this.lastVisible = visible; 
    } 
} 
7

Oluşturucu hizmeti artık (Açısal 4.x itibariyle) deprecated yeni Renderer2 hizmet invokeElementMethod yok olduğunu. Ne yapabilirsiniz böyle öğeye bir başvuru elde etmektir:

const element = this.renderer.selectRootElement('#elementId'); 

Ve sonra şöyle bu unsura odaklanmaktadır için kullanabilirsiniz:

element.focus(); 

Daha selectRootElementhere nasıl çalıştığı hakkında :

DÜZENLEME: eleman odaklı almaz

ise sık karşılaşılan bir sorun elemanı hazır olmamasıdır. (örneğin: devre dışı, gizli vb.). Bunu yapabilirsiniz:

setTimeout(() => element.focus(), 0); 

Bu yeni VM sırayla çalışacak bir macrotask yaratacak, böylece eleman etkinse odağı düzgün çalışacaktır.

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

@Directive({ 
selector: '[autoFocus]', 
}) 
export class FocusDirective implements AfterViewChecked { 

    constructor(private _elementRef: ElementRef) { } 

    ngAfterViewChecked() { 
    this._elementRef.nativeElement.focus() 
    } 

} 
İlgili konular