Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add attribute with renderer using a directive

Tags:

angular

I want to achieve extending an HTML tag with an attribute but encapsulate this with an angular 2 component.

Let's assume the original markup using my Angular 2 component foo

<div foo="x"></div>

The foo attribute should transform the div like:

<div some-other-fancy-attribute="x"></div>

First I tried implementing a directive but I could not figure out how to add another attribute to the hosting element using Renderer from angular/core.

Then I read about Angular 2 components using an attribute selector like [foo]. I liked the idea of using a template to render some-other-fancy-attribute.

However, the template get's rendered AFTER the tag so I end up with:

<div foo="x">some-other-fancy-attribute="x"

Isn't there an easy way to encapsulate some attribute creation? Thought this is a trivial one but it gives me more headache than expected.

like image 240
mbue Avatar asked Sep 23 '16 15:09

mbue


People also ask

What are attribute directives with example?

The attribute directive changes the appearance or behavior of a DOM element. These directives look like regular HTML attributes in templates. The ngModel directive which is used for two-way is an example of an attribute directive.

What is the use of attribute directives?

In summary, an attribute directive changes the appearance or behavior of a DOM element. There are three kinds of directives in Angular namely: Components - This is basically a directive with a template. Structural directives – The structural directive changes the DOM layout by adding and removing DOM elements.

How do you use a directive?

We can use attribute directives to change the style of DOM elements. These directives are also used to hide or show particular DOM elements conditionally. Angular provides many built-in Attribute Directives like NgStyle, NgClass, etc. We can also create our own custom Attribute Directives for our desired functionality.


1 Answers

If I understood you right.. your idea is good, should work!

See this plunker: https://plnkr.co/edit/YctUpK9r9AqIk0D1qvgZ?p=preview

EDIT: updated to use Renderer2

import {Component, Directive, NgModule, ElementRef, Renderer2, ViewChild} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'

@Directive({
  selector: '[foo]'
})
export class MyFancyDirective {

  constructor (private _elRef: ElementRef, private _renderer: Renderer2) { console.log('!'); }

  ngOnInit() {
    this._renderer.setAttribute(this._elRef.nativeElement, 'another-fancy-attribute', 'HERE I AM !!');
  }

}

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2 #header foo (click)="headerClicked()">Hello {{name}}</h2>
    </div>
  `,
})
export class App {

  @ViewChild('header', { static: true }) header: ElementRef;

  name:string;
  constructor() {
    this.name = 'Angular2'
  }

  headerClicked() {
    console.dir(this.header.nativeElement.attributes['another-fancy-attribute'].value);
  }
}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, MyFancyDirective ],
  bootstrap: [ App ]
})
export class AppModule {}
like image 182
slaesh Avatar answered Sep 25 '22 21:09

slaesh