Emilio Ferrucci
Emilio Ferrucci

Reputation: 627

Angular2 directives modifying its html host

I'm using Angular 2 and I would like a directive to modify the behaviour of its host html element. For example, I would like an InnerDirective with selector '[inner-directive]' such that:

@Component({
selector: '[outer-component]'
template: `
<div
  inner-directive
></div>
`
})
class outerComponent{
someAttribute: boolean;
}

is the same as

@Component({
selector: '[outer-component]'
template: `
<div
  [ngClass] = "{'some-class': someAttribute}"
></div>
`
})
class outerComponent{
someAttribute: boolean;
}

I don't want InnerDirective to be a component with its own template doing the job (with someAttribute getting passed down) because that would create a redundant html element.

More generally I would like to do whatever can be achieved by putting an empty component inside another component (with the aforementioned html redundancy), by getting the inner component to be a directive instead. That way my "leaves" can all be directives.

Thank you very much for your help.

Upvotes: 1

Views: 4523

Answers (2)

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657486

@Directive({
  selector: '[innerDirective]',
  host: {'[class.some-class]': 'innerDirective'}
})
class InnerDirective {
  @Input() innerDirective: boolean;
}
  • host: {'[class.some-class]': 'someAttribute'} binds the value of the innerDirective input to some-class on the host element.

  • An input with the same name as the selector (@Input() innerDirective: boolean;) allows terse binding syntax (shown below)

@Component({
  selector: '[outer-component]',
  directives: [InnerDirective],
  template: `
<div [innerDirective]="someAttribute"></div>`
})
class outerComponent{
  someAttribute: boolean;
}
  • [innerDirective]="someAttribute" binds the someAttribute value to the innerDirective input of InnerDirective.

Upvotes: 3

Thierry Templier
Thierry Templier

Reputation: 202206

It's typically what attribute directive aims to. It allows to change the appearance or behavior of the element it applies on.

Here is a sample:

@Directive({
  selector: '[inner-directive]'
})
export class InnerDirective {
  constructor(el: ElementRef) {
    el.nativeElement.style.backgroundColor = 'yellow';
  }
}

Update

You can leverage the host attribute when defining your directive

@Directive({
  (...)
  host: {
    '[class.myClass]': 'displayClass',
    '[attr.someAttr]': 'someAttrValue',
    '[attr.otherAttr]': 'someValue'
  }
})
export class InnerDirective {
  @Input('innner-directive')
  someValue: string;

  constructor() {
    // myClass is added on the host
    this.displayClass = true;

    // myClass isn't added on the host
    // this.displayClass = false;

    this.someAttrValue = 'some value';
  }

  ngOnInit() {
    console.log(this.someValue);
  }
}

Upvotes: 1

Related Questions