2016-01-14 24 views
6

Sto cercando di aggiornare un'app Angular 1 su Angular 2 e sto avendo un problema con una delle mie vecchie direttive.Angular2 evento di attivazione per aggiungere la classe

L'idea è semplice. Quando un campo di input è focalizzato, è necessario aggiungere una classe (md-input-focus) e un'altra (md-input-wrapper). Quindi questo processo dovrebbe essere invertito in caso di "sfocatura" - cioè messa a fuoco persa.

mia vecchia direttiva incluso semplicemente le linee

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

ecc ...

ho, ovviamente, il classico per iniziare la mia direttiva, ma sono a corto di ..... abilità

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

Qualsiasi aiuto sarebbe apprezzato.

UPDATE:

Il codice HTML sarà simile (prima l'elemento di input è concentrata):

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

e poi

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

dopo.

L'elemento di ingresso è l'unico che può ricevere un evento fuoco (e quindi l'obiettivo per la direttiva), tuttavia il genitore <div> richiede l'aggiunta di classe e la rimozione.

Aiuto ulteriore

Please see Plunker for help/explanation - sarebbe bello se qualcuno potrebbe aiutare

risposta

5

Aggiornamento

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

originale

questo può facilmente b e fatto senza ElementRef e Renderer (ciò che si dovrebbe lottare per in Angular2) definendo binding ospitanti:

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

o un po 'più concisa

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

ho provato solo a Dart dove funziona benissimo. Spero di averlo tradotto correttamente in TS.

Non dimenticare di aggiungere la classe allo directives: dell'elemento in cui si utilizza la direttiva.

+0

Capisco la logica del codice di Gunter ma penso che non lo fa abbastanza in forma. La classe dovrebbe essere aggiunta all'elemento genitore. HTML:

Questo è il motivo per cui sono un po 'bloccato perché non so come fare riferimento a un elemento padre di un elemento per cui è stata attivata la direttiva? –

+0

Ok, ma il genitore non è il componente genitore, ma il tag principale? In questo caso avresti bisogno di 'ElementRef'. Non c'è 'closest()' in Angolare. Vorresti comunque usarlo o è solo ".parentElement" ok? –

+0

Ho aggiornato la mia domanda per mostrare l'HTML a cui deve essere collegata la direttiva nel caso in cui aiuti :) –

0

Il nome del selettore deve essere dentro "[]", come illustrato di seguito

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

Oltre alle risposte precedenti, se non si desidera aggiungere una direttiva, per il componente specifico (si dispone già di una direttiva per un componente genitore, si utilizza la pagina ionico 2 o qualcos'altro), si inietta il renderer aggiungendo private _renderer: Renderer nel costruttore di pagina e aggiornare l'elemento con l'obiettivo evento come questo:

html:

(dragstart)="dragStart($event)" 

TS:

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

Modifica: per rimuovere la classe solo fare:

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

Risposta molto concisa e funziona alla grande. L'unico cambiamento che farei è che è dattiloscritto dare "ev" un tipo esplicito di "Evento". dragStart (ev: Event) {.... –