Angular2 on focus event to add class

angular 2 focus on next input
nativeelement focus not working
angular focus on next input
angular focus event
angular get focused element
angular material focus input
angular set focus on form control
angular autofocus

I'm looking to update an Angular 1 app to Angular 2 and am having an issue with one of my old directives.

The idea is simple. When an input field is focused a class should be added (md-input-focus) and another be removed (md-input-wrapper). Then this process should be reversed on "blur" event - i.e. focus lost.

My old directive simply included the lines

.directive('mdInput',[
    '$timeout',
    function ($timeout) {
        return {
            restrict: 'A',
            scope: {
                ngModel: '='
            },
            link: function (scope, elem, attrs) {
                var $elem = $(elem);
                $elem.on('focus', function() {
                      $elem.closest('.md-input-wrapper').addClass('md-input-focus')
                })
                .on('blur', function() {
                 $(this).closest('.md-input-wrapper').removeClass('md-input-focus');
                })
             }

etc...

I obviously have the classic start to my directive but have run out of.....skill

import {Directive, ElementRef, Renderer, Input} from 'angular2/core';

@Directive({
      selector: '.mdInput',

})

export class MaterialDesignDirective {
      constructor(el: ElementRef, renderer: Renderer) {
           // Insert inciteful code here to do the above
      }
}

Any help would be appreciated.

UPDATE:

The HTML would look like (before the input element was focused):

<div class="md-input-wrapper">
   <input type="text" class="md-input">
</div>

and then

<div class="md-input-wrapper md-input-focus">
   <input type="text" class="md-input">
</div>

after.

The input element is the only one which can receive a focus event (and therefore the target for the directive) however the parent <div> requires the class addition and removal.

Further help

Please see Plunker for help/explanation - would be great if someone could help

Update

@Directive({selector: '.md-input', host: {
  '(focus)': 'setInputFocus(true)',
  '(blur)': 'setInputFocus(false)',
}})
class MaterialDesignDirective {
  MaterialDesignDirective(private _elementRef: ElementRef, private _renderer: Renderer) {}
  setInputFocus(isSet: boolean): void {
    this.renderer.setElementClass(this.elementRef.nativeElement.parentElement, 'md-input-focus', isSet);
  }
}

Original

This can easily be done without ElementRef and Renderer (what you should strive for in Angular2) by defining host bindings:

import {Directive, ElementRef, Renderer, Input} from 'angular2/core';

@Directive({
      selector: '.mdInput',
      host: {
        '(focus)':'_onFocus()',
        '(blur)':'_onBlur()',
        '[class.md-input-focus]':'inputFocusClass'
      }

})

export class MaterialDesignDirective {
      inputFocusClass: bool = false;

      _onFocus() {
        this.inputFocusClass = true;
      }

      _onBlur() {
        this.inputFocusClass = false;
      }
}

or a bit more terse

@Directive({
      selector: '.mdInput',
      host: {
        '(focus)':'_setInputFocus(true)',
        '(blur)':'_setInputFocus(false)',
        '[class.md-input-focus]':'inputFocusClass'
      }

})

export class MaterialDesignDirective {
      inputFocusClass: bool = false;

      _setInputFocus(isFocus:bool) {
        this.inputFocusClass = isFocus;
      }
}

I tried it only in Dart where it works fine. I hope I translated it correctly to TS.

Don't forget to add the class to the directives: of the element where you use the directive.

Angular2 input component Add class on focus, _el; } @HostListener('focus', ['$event']) onFocus(e) { this.renderer. use this directive onFocus on element (on which you want to add class). Form field focus is something we have to deal with a lot when it comes to building forms. When a user clicks an “update” button we want to automatically focus them on the field that needs updating.

In addition to previous answers, if you don't want to add a directive, for the specific component (you already have a directive for a parent component, you are using Ionic 2 page or something else), you inject the renderer by adding private _renderer: Renderer in the page constructor and update the element using the event target like this:

html:

(dragstart)="dragStart($event)"

TS:

dragStart(ev){
    this._renderer.setElementClass(ev.target, "myClass", true)
}

Edit: to remove the class just do:

dragEnd(ev){
    this._renderer.setElementClass(ev.target, "myClass", false)
}

theCodeCampus → Angular: Set Focus on Element, Want to set focus on an HTML element in your Angular app? The following Step-by-step. Let's start by adding an input element and a button to our component's template. We give the input element an ID and pass it to the method called in the button's click event, like this: export class AppComponent {}  To bind to a DOM event, surround the DOM event name in parentheses and assign a quoted template statement to it. The following example shows an event binding that implements a click handler: <button (click)="onClickMe()">Click me!</button>

The name of the selector has to be inside "[ ]", as shown below

@Directive({
  selector: '[.mdInput]',
  host: {
    '(focus)':'_setInputFocus(true)',
    '(blur)':'_setInputFocus(false)',
    '[class.md-input-focus]':'inputFocusClass'
  }
})

Angular ng-content and Content Projection, detecting the focus and blur events on the native html input, and based on that we add or remove the focus CSS class on the host element via  A click, hover, or a keyboard action are all events that you can use to call component logic within Angular. That's what Angular event binding is all about. It's one-way data binding, in that it sends information from the view to the component class. This is opposite from property binding, where data is sent from the component class to the view.

If you want to catch the focus / blur events dynamiclly on every input on your component :

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements AfterViewInit {
  name = 'Angular focus / blur Events';

  constructor(private el: ElementRef) {
  }

  ngAfterViewInit() {
       // document.getElementsByTagName('input') : to gell all Docuement imputs
       const inputList = [].slice.call((<HTMLElement>this.el.nativeElement).getElementsByTagName('input'));
        inputList.forEach((input: HTMLElement) => {
            input.addEventListener('focus', () => {
                input.setAttribute('placeholder', 'focused');
            });
            input.addEventListener('blur', () => {
                input.removeAttribute('placeholder');
            });
        });
    }
}

Checkout the full code here : https://stackblitz.com/edit/angular-wtwpjr

User input, You can use Angular event bindings to respond to any DOM event. button> {{​clickMessage}}` }) export class ClickMeComponent { clickMessage = ''; onClickMe() { this. To fix this issue, listen to both the Enter key and the blur event. The user can add a hero by typing the hero's name in the input box and clicking Add. I am going to share with you a useful list of Angular 7 Event Types for Event Binding. Angular offers plenty of event types to communicate with your app. Events in Angular 7 helps you to trigger an action on specific condition like click, scroll, hover, focus, submit etc.

Optimizing Events handling in Angular, And as a bonus we will add .prevent and .stop modifiers that would To handle events Angular uses EventManager class. It has a In case of select , Esc should close the dropdown and move focus from menu back to select. Select Content of Textbox on Focus using Angular 2. We can select content of HTML element using element.select(). But onmouseup action the selected text by script will be deselected. So we have to disable onmouseup action.

onblur Event, The onblur event occurs when an object loses focus. The onblur event is most often used with form validation code (e.g. when the user leaves a form field). Tip:​  Add the click event handlerlink. Rename the component's hero property to selectedHero but don't assign it. There is no selected hero when the application starts. Add the following onSelect() method, which assigns the clicked hero from the template to the component's selectedHero.

HostListener & HostBinding • Angular, When that event gets fired on the host element it calls the associated function. So if we add this function to our directive class: TypeScript. Copy @HostListener  Component events with EventEmitter and @Output in Angular. Angular components are the fundamental building blocks of architecture. Once you’ve understood component architecture, you can build a picture in your head as to how to assemble your interface based on data communication.

Comments
  • I understand the logic of your code Gunter but I think it doesn't quite fit. The class should be added to the parent element. HTML: <div class="md-input-wrapper"> <input type="text" class="md-input"> </div> This is what I am a little stuck on as I don't know how to reference a parent element of an element which the directive is triggered for?
  • Ok, but the parent is not the parent component, but the parent tag? In this case you'd need the ElementRef. There is no closest() in Angular. Would you still want to use that or is just .parentElement ok?
  • I have updated my question to show the HTML which the directive should be attached to in case it helps :)
  • I updated my question. Again, I hope I didn't add bugs while translating from Dart to TS.
  • Thanks Gunter. I would be happy if .parent works. Can you show how I would use it? Your code works in ts although book should be Boolean :)
  • Very concise answer and works great. The only change I would make is since it is typescript give "ev" an explicit type of "Event". dragStart(ev: Event){....