In my app, I tried to place a button that shows/hides an input
field with a boolean
component property. If the button shows the input
, focus should be set on the input
. But it seems not to work. If I remove the *ngIf
the focus directive works fine.
I created a plunker that shows what I mean. It's kind of difficult to describe my problem.
HTML in a component:
<input *ngIf="filterShow.options"
[focus]="filterFocus.options"
[(ngModel)]="filter.options">
<button type="button"
(click)="setShowFilter('options')">
focus
</button>
setShowFilter()
method:
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', []);
});
}
}
The * syntax means that ngIf is a structural directive, meaning that it affects the structure of the page.
NgIflink. A structural directive that conditionally includes a template based on the value of an expression coerced to Boolean.
The ngIf Directive in Angular10 is used to remove or recreate a portion of HTML element based on an expression. If the expression inside it is false then the element is removed and if it is true then the element is added to the DOM. Syntax: <li *ngIf='condition'></li>
The ng-focus directive tells AngularJS what to do when an HTML element gets focus. The ng-focus directive from AngularJS will not override the element's original onfocus event, both will be executed.
EventEmitter
s are for @Output
s, not for @Input
s. Try something like this instead:
@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', []);
}
}
}
A cleaner way to achieve this without having to use a directive is to use <label>
instead of <button>
and use css to style it like a button. For example,
<label for="myInput"></label>
<input id="myInput"></input>
This way you can achieve focus even with the presence of *ngIf
because the <input>
is now bound to the <label>
. Also, Angular2 documentation website warns about the use of ElementRef
because of the security vulnerability it poses.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With