5

I have a template which has textbox, one 'span' tag and one 'div' tag.

'div' tag has 'selectedColor' custom directive. I want to change background color of 'span' and 'div' tags when input value is changed.

So finally I want my directive to react on input change and sets background color of 'div' tag.

I also want to change 'span' background color on input value change event.

Plunker

boot.ts

import {Component,bind} from 'angular2/core';

import {bootstrap} from 'angular2/platform/browser';
import {FORM_DIRECTIVES} from 'angular2/form';
import {selectedColorDirective} from 'src/directive';
import {Directive, ElementRef, Renderer, Input} from 'angular2/core';

@Component({
  selector: 'my-app',
  template: `
      <input type="text" [(ngModel)]="color"  />
      <br>
      <span > I'm {{color}} color <span>
      <div [mySelectedColor]="color"> I'm {{color}} color </div>
    `,
    directives: [selectedColorDirective]
})

export class AppComponent{

  color:string;
  constructor(el:ElementRef,renderer:Renderer)
  {
    this.color="Yellow";
    renderer.setElementStyle(el, 'backgroundColor', this.color);
  }
 }

    bootstrap(AppComponent, []);

directive.ts

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

@Directive({

  selector:"[mySelectedColor]", 
    host: {
    // '(keyup)': 'changeColor()',
    '(blur)': 'changeColor()',
  }

  })

  export class selectedColorDirective{ 

    @Input('mySelectedColor') selectedColor: string;

    constructor(el: ElementRef, renderer: Renderer) {
        //el.nativeElement.style.backgroundColor = 'yellow'; 
       renderer.setElementStyle(el, 'backgroundColor', this.selectedColor);
    } 

    changeColor(color:string)
    {
       console.log('Changed Detection' + " " + selectedColor);
       //this.renderer.setElementStyle(this.el, 'backgroundColor', this.color);
     }
  }

Moreover if you could explain more about @Input decorator.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
nyks
  • 2,103
  • 6
  • 14
  • 17
  • There are many ways to do this. Is there a reason you want to use a directive? You could just assign classes to the elements where you want to change the color `
    ` or `[style.color]="color"`. Please explain a bit more about what you actually try to accomplish.
    – Günter Zöchbauer Jan 18 '16 at 07:54
  • Yes there are many ways. But want to do it directive way because want to explore more about it. – nyks Jan 18 '16 at 07:56

2 Answers2

4

You can create an @Input() someName: SomeType in your directive and bind it to a field or function in the parent component like

<div [mySelectedColor]="color" 
    [someName]="someFieldInParent"> I'm {{color}} color </div>

Another way is to query the directive in the parent component and invoke functions or set fields directly.

export class AppComponent{
  @ViewChild(selectedColorDirective) myDirective: selectedColorDirective;

  ngAfterViewInit() {
    myDirective.changeColor('red');
  }
}

You can also bind directly to class and assign CSS by using these class selectors.

See for example this http://plnkr.co/edit/nm8RgxMtqdEDyQWQGeUp?p=preview

Using a binding as selector at the same time is not supported currently, therefore you have to list the directive selector and the property you bind to each. Only [(myDirective)]="someField" seems to be supported.

I used

host: {
  '(keyup)': 'changeColor()',
  '[style.color]': 'selectedColor', // <==
}

for setting the style (I also changed the AppComponent to use this way). This is preferred to using ElementRef and Renderer. I used ElementRef and Renderer for the <span> tag though because I don't see another way from the directive on another element.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • Modifying an element `` from a directive that is added to another tag is IMHO a pretty bad idea. Is that really what you want? – Günter Zöchbauer Jan 18 '16 at 08:06
  • Answer is great. but how can I call changeColor function written in directive when I change component's input field value and change bgcolor with ElementRef and Rendrer? is it possible? – nyks Jan 18 '16 at 08:55
  • What do you mean by "call"? You don't want to use binding but directly call the method? Like shown here http://stackoverflow.com/questions/34846048/calling-function-in-child-container-from-parent-in-angular-2/34847546#34847546 ? – Günter Zöchbauer Jan 18 '16 at 08:57
  • Not sure if this is what you want http://plnkr.co/edit/QUf67I6qsQYk7n2gQAI9?p=preview I added a binding for the `blur` event (``) and I added the binding to `selectedColor` (`
    (div) I'm {{color}} color
    `) because otherwise the binding and the background color set by the function call interfere. I also changed `changeColor` to set the color passed as argument instead of the one bound to `selectedColor`. Hope this helps.
    – Günter Zöchbauer Jan 18 '16 at 10:27
  • @GünterZöchbauer - hey, do you know how to call the component class method when I was inside its directive? – Ng2-Fun Apr 20 '17 at 04:07
-1

Easiest way, in your directive:

constructor(el: ElementRef) {
 el.nativeElement.style.backgroundColor = "yellow";
}
Vlado Tesanovic
  • 6,369
  • 2
  • 20
  • 31