web-dev-qa-db-fra.com

Angular2 on focus event pour ajouter un cours

Je cherche à mettre à jour un Angular 1 application sur Angular - 2 et j'ai un problème avec l'une de mes anciennes directives.

L'idée est simple. Lorsqu'un champ d'entrée est activé, une classe doit être ajoutée (md-input-focus) et une autre doit être supprimée (md-input-wrapper). Ensuite, ce processus devrait être inversé lors d’un événement "flou" - c’est-à-dire que la focalisation est perdue.

Mon ancienne directive comprenait simplement les lignes

.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...

J'ai évidemment le début classique de ma directive mais suis à court de compétences .....

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
      }
}

Toute aide serait appréciée.

METTRE À JOUR:

Le code HTML ressemblerait à (avant que l'élément d'entrée ne soit focalisé):

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

et alors 

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

après.

L'élément input est le seul à pouvoir recevoir un événement de focus (et donc la cible de la directive). Toutefois, le parent <div> requiert l'ajout et la suppression de la classe.

Aide supplémentaire

S'il vous plaît voir Plunker pour l'aide/explication - serait génial si quelqu'un pourrait aider

7
Mad Eddie

Mettre à jour

@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

Cela peut facilement être fait sans ElementRef et Renderer (ce que vous devez rechercher dans Angular2) en définissant des liaisons d'hôtes:

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;
      }
}

ou un peu plus laconique

@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;
      }
}

Je l'ai essayé uniquement dans Dart où cela fonctionne bien. J'espère que je l'ai traduit correctement en TS.

N'oubliez pas d'ajouter la classe au directives: de l'élément où vous utilisez la directive.

5
Günter Zöchbauer

Outre les réponses précédentes, si vous ne souhaitez pas ajouter de directive, pour le composant spécifique (vous avez déjà une directive pour un composant parent, vous utilisez la page Ionic 2 ou autre), vous injectez le rendu en ajoutant private _renderer: Renderer dans le constructeur de la page et mettez à jour l'élément en utilisant la cible de l'événement comme ceci:

html:

(dragstart)="dragStart($event)"

TS:

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

Edit: pour supprimer la classe, il suffit de:

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

Le nom du sélecteur doit être dans "[]", comme indiqué ci-dessous

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

Si vous souhaitez capturer les événements focus/blur de manière dynamique sur chaque entrée de votre composant:

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');
            });
        });
    }
}

Commander le code complet ici: https://stackblitz.com/edit/angular-wtwpjr

0
abahet