Angular2 insert custom attribute in tag with directive
Asked Answered
M

3

6

I have an angular 2 project and I'm using PrimeNG. I'm using a special tag with a lot of custom attributes and these attributes are always the same for this tag. I want to externalize these attributes and I created a custom directive used to add all attributes I need. The problem is that some of these attributes aren't native and maybe they aren't recognized. I get the error "Failed to execute 'setAttribute' on 'Element': '[myCustomAttribute]' is not a valid attribute name.

This is my directive:

@Directive({
  selector: '[def-calendar]'
})
export class DefaultCalendarDirective {

  constructor(private _elRef: ElementRef, private _renderer: Renderer2) {
  }

  ngOnInit() {
    this._renderer.setAttribute(this._elRef.nativeElement, '[yearRange]', '1900:2100');
  }
}

Anyone know how can I fix it? I don't know if is there a way to copy the element such as string and manipulate the string adding my attributes.

Thanks Fabrizio

Mixedup answered 21/6, 2017 at 8:49 Comment(0)
K
2

This might be useful for you. Angular2 add attribute with Renderer using a directive.

I think the square bracket between the yearRange is the culprit. Hope this helps.

Kalisz answered 14/7, 2017 at 9:47 Comment(0)
H
1

You can't use renderer.setAttribute(...) to set attributes that don't belong to the native HTML element you're using.
yearRange isn't even an attribute to be accurate for any native HTML element. It should be declared as an input in class of the directive in order to set values for it properly:

@Directive({
  selector: '[def-calendar]'
})
export class DefaultCalendarDirective implements OnInit {

  @Input() yearRange: string = '1900:2100';

  constructor() {
  }

  public ngOnInit() {}
}

You can also change the input value by passing it a string (or you can also use binding instead) when you're using the directive on an element.

<someElement def-calendar yearRange="1900:2100"></someElement>
Homologize answered 21/6, 2017 at 9:10 Comment(6)
Hi and thanks for reply. So I don't need to set the value, I need to manipulate the tag adding some attributes. Let me explain: I have this <p-calendar def-calendar [(ngModel)]="clientFilter.dateEnd" dateFormat="></p-calendar> and I want to have this: <p-calendar def-calendar [(ngModel)]="clientFilter.dateEnd" dateFormat=" [monthNavigator]="true" [yearNavigator]="true" yearRange="2000:2030"></p-calendar>Mixedup
You can't "add" attributes. Either you use inputs or you use the default attributes of the element you're adding the directive to (disabled or value in case of button for example).Homologize
And based on what you wrote, you need to define the inputs dateFormat, monthNavigator, and yearRange in your directive's class to make it work. I don't see any other way for doing this.Homologize
Ok this is a bad thing.. I was looking for a way to manipulate the tag instead add attributes, I don't want to add inputs on tag, my target is to clean the codeMixedup
I don't see why you have a problem using inputs. It's the only way to "add custom attributes" to the component/directive you're creating. If you don't exactly know what an input is, have a look at the input doc of Angular. It should help you.Homologize
I know what's an input, i want to clear my code and I want to centralize the common code and avoid to write the same things everywhere. I tried to create a component but I lost the form validation controlMixedup
D
0

We can use setAttribute method of Renderer2 class

import {Directive, ElementRef, Renderer2, Input, HostListener} from '@angular/core';

@Directive({
  selector: '[DirectiveName]'
})
export class DirectiveNameDirective {
 constructor(public renderer : Renderer2,public hostElement: ElementRef){}
ngOnInit() {
      this.renderer.setAttribute(this.hostElement.nativeElement, "data-name", "testname");
      }
    }
Dovev answered 26/7, 2017 at 11:33 Comment(5)
Hi, I tried your solution but I get this error: "Failed to execute 'setAttribute' on 'Element': 'data- name' is not a valid attribute name."Mixedup
Hi @FabrizioP There is space between data- name, please remove space and check, I will change my answer.Dovev
Hi and thanks, if I set data-name it works but I need to add *ngIf and this not worksMixedup
Hi You can directly use *ngIf to element, Using directive we can set data attributeDovev
Of course, I can.. But to keep the code clean I want to create a directive accepting a value and make some checks on directive to show or hide the element.Mixedup

© 2022 - 2024 — McMap. All rights reserved.