Cannot read Property 'setAttribute' of null com ngFor

Asked

Viewed 770 times

0

I have an ngFor that adds several strings, and this data comes from an api

<p class="teste" *ngFor="let element of objeto_retorno" >Filial {{ element.FILIAL }} = {{ element.TOTAL }} </p>

and no ts:

  ngOnInit() {
    document.querySelector('.teste').setAttribute('class','cor')
  }

But he keeps making that mistake: Cannot read Property 'setAttribute' of null

I believe it is because of ngFor, but I’m not able to solve it, someone can give me a light?

  • document.querySelector('.teste') is returning null....

  • Yeah, I figured it out, but how do I fix it? Because he’s taking the class, and I even put it on to get the ID and it won’t go

  • I tested here with class and tb was not, but by id gave.

  • I’m not sure, but I believe that at the moment ngOnInit runs the view is not fully loaded and possibly the element does not yet exist. Take a look at life Cycle Hooks https://angular.io/guide/lifecycle-hooks#ondestroy. Try replacing ngOnInit with ngAfterViewInit

  • I tested here, but still null

  • It worked here: https://stackblitz.com/edit/angular-fvhftk

  • yet here it doesn’t work, and I have no idea why

Show 2 more comments

2 answers

2


I recommend using Angular itself, you don’t have to do things like that manually.

Use querySelector and querySelectorAll for elements that change constantly with Angular is quite unnecessary and on top of that problematic.

And then apply directly (if it is in fact at the time that the elements are populated/generated):

<p class="teste" *ngFor="let element of objeto_retorno" >Filial {{ element.FILIAL }} = {{ element.TOTAL }} </p>

Just for the record, the problem is that even ngAfterViewInit resolve first, if the data is repopulated the DOM is changed, usually the elements do not even exist yet, even if the screen has been loaded, even if it is imperceptible to you maybe the elements take a few milliseconds to be generated, and so something like that will not work right:

 document.querySelector('.teste').setAttribute('class','cor')

But if what you want is to apply as an event occurs then do something like:

<p [class]="propriedadeDaClasse ? 'cor': 'teste'" *ngFor="let element of objeto_retorno" >Filial {{ element.FILIAL }} = {{ element.TOTAL }} </p>

This example above would be the equivalent of setAttribute (changing the class), note that propriedadeDaClasse can be an "if" too, something like:

<p [class]="x != y ? 'cor': 'teste'" *ngFor="let element of objeto_retorno" >Filial {{ element.FILIAL }} = {{ element.TOTAL }} </p>

Both the hypothetical variable propriedadeDaClasse, how much x and y must be within the scope of this of your class, something like, examples:

export class FooBar {
    propriedadeDaClasse = false;
}

Or:

export class FooBar {
    x = 1;
    y = 2;
}

Now if you want to keep the "test" class along with "color" you will have to do so:

<p [class]="propriedadeDaClasse ? 'teste cor': 'teste'" *ngFor="let element of objeto_retorno" >Filial {{ element.FILIAL }} = {{ element.TOTAL }} </p>

So in this way Angular itself will understand when the DOM is changed and apply the classes as needed.


If they are classes (varied colors) the best would be to apply the color to a variable, something like:

export class FooBar {
    mainColor = ''; //começa sem cor, mas pode trocar '' por algo como 'cor'

     ...
}

Then in the:

<p [class]="mainColor + ' teste'" *ngFor="let element of objeto_retorno" >Filial {{ element.FILIAL }} = {{ element.TOTAL }} </p>

Thus concatenates mainColor + ' teste' both classes, which will generate things like:

class="cor1 teste"

or:

class="cor2 teste"

Ai within the class just change the color at any time, for example:

this.mainColor = 'cor1';

Or:

this.mainColor = 'cor2';

And in css:

.cor1 {
    color: red;
}

.cor2 {
    color: blue;
}

They are just examples, you adapt to your need

  • Is there any way to apply more than one if in there? pq I need it to change to another color if the value is greater than 8 and then to another if it is greater than 10

  • @Maria this is an example of if [class]="x != y ? 'cor': 'teste'", now want more colors the best would be to set the value in a variable in the class and apply directly, I will edit the answer.

  • @Maria ready, answer edited.

0

Try to do the querySelector by an id.

document.querySelector('#idteste').setAttribute('class','cor');

console.log('document.querySelector(\'#idteste\')', document.querySelector('#idteste'))
console.log('document.querySelector(\'.teste\')', document.querySelector('.teste'))
<p id="idteste" class="teste" *ngFor="let element of objeto_retorno" >

Edit: Plunker

It has to be put on ngAfterViewInit for at this stage the GIFT will be fully charged.

  • tested and keeps giving null

  • Instead of being in the ngOnInit puts in the ngAfterViewInit, I think it’s because the DOM then loads with id and class.

  • same thing, ta dando null

  • objeto_retorno is empty?

  • ta nao, ta returning several string

  • Well... I set an example in the plunker... when you’re in the ngOnInit makes the mistake, but ngAfterViewInit don’t give... take a look here

  • I see, but for what reason here is not working? the data that is appearing comes from an api

Show 2 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.