Angular2 с использованием *ngIf с директивой focus?
В моем приложении я попытался разместить кнопку, которая показывает / скрывает поле ввода с логическим свойством компонента. Если кнопка показывает вход, фокус должен быть установлен на входе. Но, похоже, не работает. Если я удалю *ngIf
директива фокусировки работает отлично.
Я создал поршень, который показывает, что я имею в виду. Трудно описать мою "проблему".
HTML в компоненте
<input *ngIf="filterShow.options"
[focus]="filterFocus.options"
[(ngModel)]="filter.options">
<button type="button"
(click)="setShowFilter('options')">
focus
</button>
функция setShowFilter ()
private setShowFilter(filter: string) {
this.filterShow[filter] = !this.filterShow[filter];
/* reset filter */
this.filter[filter] = "";
this.filterFocus[filter].emit(true);
}
focus.directive.ts
@Directive({
selector: '[focus]'
})
export class FocusDirective implements OnInit {
@Input('focus') focusEvent: EventEmitter<boolean>;
constructor(private elementRef : ElementRef,
private renderer : Renderer ) { }
ngOnInit() {
this.focusEvent.subscribe(event => {
this.renderer
.invokeElementMethod(this.elementRef.nativeElement, 'focus', []);
});
}
}
3 ответа
EventEmitters для выходов, а не для входов. Попробуйте что-то вроде этого:
@Directive({
selector: '[focus]'
})
export class FocusDirective implements OnChanges {
@Input('focus') focus: boolean;
constructor(private elementRef : ElementRef,
private renderer : Renderer ) { }
ngOnChanges() {
if (this.focus) {
this.renderer
.invokeElementMethod(this.elementRef.nativeElement, 'focus', []);
}
}
}
В большинстве случаев это не работает, потому что за событием фокуса следуют другие события. Таким образом, элемент потерял фокус. Нам нужно использовать setTimeout
чтобы поместить его в конец очереди планировщика задач:
import { Directive, OnChanges, Input, ElementRef } from "@angular/core";
@Directive({
selector: '[focus]'
})
export class FocusDirective implements OnChanges {
@Input('focus') focus: boolean;
constructor(private elementRef : ElementRef) { }
ngOnChanges() {
if (this.focus) {
setTimeout(() => { this.elementRef.nativeElement.focus(); }, 0);
}
}
}
Более чистый способ достичь этого без использования директивы - это использовать <label>
вместо <button>
и используйте CSS, чтобы оформить его как кнопку. Например,
<label for="myInput"></label>
<input id="myInput"></input>
Таким образом, вы можете достичь фокуса даже при наличии *ngIf
поскольку <input>
теперь связан с <label>
, Кроме того, веб-сайт документации Angular2 предупреждает об использовании ElementRef
из-за уязвимости безопасности, которую он представляет.