Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

*ngIf with focus directive

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', []);
    });
  }
}
like image 845
Max Solid Avatar asked Mar 31 '17 18:03

Max Solid


People also ask

What is * in * ngIf?

The * syntax means that ngIf is a structural directive, meaning that it affects the structure of the page.

Is ngIf a directive?

NgIflink. A structural directive that conditionally includes a template based on the value of an expression coerced to Boolean.

What is ngIf directive in angular?

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>

What is focus in angular?

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.


2 Answers

EventEmitters are for @Outputs, not for @Inputs. 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', []);
    }
  }
}
like image 122
adharris Avatar answered Sep 25 '22 00:09

adharris


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.

like image 23
Rachita Joshi Avatar answered Sep 23 '22 00:09

Rachita Joshi