2

I have two tables in db, and from the apis, i'm creating loops:

<div *ngFor="let laptop of laptops">
    some content
    <!-- Producer / Name -->
    <div *ngFor="let producer of producers">
         <div class="title" *ngIf="producer.id === laptop.producerId>
               {{producer.name}} {{laptop.model}}
         </div>

    </div>
</div>

I have 70 producer names and foreign key from laptops to producer table. My e.g. laptop has got producerId = 3 and i want to loop for each producers and display only this which meets the condition. It works but when i see DOM, it scares me. 70 divs! I've read this: *ngIf and *ngFor on same element causing error

and after this:

 <ng-container *ngFor="let producer of producers>
        <div class="title" *ngIf="producer.id === laptop.producerId>
             {{producer.name}} {{laptop.model}}
        </div>
</ng-container>

I have in DOM:

enter image description here

Is that correct result? Or is there any way to create only that div which meets the condition? enter image description here

Sarun UK
  • 6,210
  • 7
  • 23
  • 48
  • 3
    The comments are used by Angular for bindings as anchors or similar. You can't get rid of them. – Günter Zöchbauer Mar 08 '18 at 19:43
  • So that’s correct result? These comments won’t slow my app? I used them in many other places in my app –  Mar 08 '18 at 19:45
  • 1
    You could use a filter pipe instead of `*ngIf` to not make `*ngFor` try to render it in the first place if an item doesn't match. I don't know how much this affects performance. You'd need to do performance checks yourself. – Günter Zöchbauer Mar 08 '18 at 19:49
  • U think about this?https://stackoverflow.com/questions/37067138/angular-2-check-if-pipe-returns-an-empty-subset-of-original-list –  Mar 08 '18 at 19:52

3 Answers3

1

As @Gunter already mentioned, this are the placeholder created for binding. This is normal.

But I'd love to restructured my data before dumping the HTML, so in terms of performance and readability it will look nice.

//once laptop and producers are retrieved from the server call below method
formatLaptopData(producers) {
    this.laptops = this.laptops.map((laptop: any)=> {
       laptop.producers = 
           producers.filter((producer: any) => laptop.producerId == producer.id);
       return laptop;
    });
}

Html

<div *ngFor="let laptop of laptops">
    some content
    <div *ngFor="let producer of laptop.producers">
         <div class="title">
              {{producer.name}} {{laptop.model}}
         </div>
    </div>
</div>
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
  • TS2339: Property 'id' does not exist on type 'never'. –  Mar 08 '18 at 20:44
  • @FreeStyle09 make it typesafe, the issue will resolve, otherwise use `any` variable for `producer` – Pankaj Parkar Mar 08 '18 at 20:46
  • yeah i added any types and it's not working :/ i edit for you code can u check that did i miss something ? –  Mar 08 '18 at 20:47
  • look my all .ts code i think i have same and it's not working :/ –  Mar 08 '18 at 20:50
  • Did i miss something ? –  Mar 08 '18 at 20:53
  • It was completely my mistake, the `.filter` condition should have `==` instead of `=`, Apologies for mistake :( – Pankaj Parkar Mar 08 '18 at 20:57
  • I don't know what is going on, but still it's not working :/ Look my picture above i changed from '=' to '==' and still nothing, in DOM is only ' –  Mar 08 '18 at 20:59
0

We can achieve it by creating a filter. Create a file FilterPipe.ts with below codes.

import {Pipe, PipeTransform} from '@angular/core';

@Pipe({
  name: 'filter'
})
export class FilterPipe implements PipeTransform {
public transform(value, keys: string, term: any) {
 if (!term) return value;
  return (value || []).filter(item => keys.split(',').some(key => 
  item.hasOwnProperty(key) && new RegExp(term, 'gi').test(item[key])));
 }
}

Now the code will be like this

<div *ngFor="let laptop of laptops">
some content
<!-- Producer / Name -->
  <div class="title" *ngFor="let producer of producers | filter : 'id' : laptop.producerId">
           {{producer.name}} {{laptop.model}}
  </div>
</div>

*Don't forget to import filter into the module.

-1

Rewriting the whole answer, I actually found out the solution for it eventually. you just need to add ;else null to the ngIf*

<div *ngFor="let producer of producers">
     <div class="title" *ngIf="producer.id === 'laptop.producerId'; else null">
           {{producer.name}} {{laptop.model}}
     </div>
</div>
Globality
  • 1
  • 1
  • This doesn't answer the question. Also, instead of using `*ngIf` for your second div, you can just do `
    `. The hidden attribute is built in, and the element will stay in the DOM. Using `*ngIf` will remove the element from the DOM if the value is falsey.
    – ps2goat Oct 06 '20 at 18:03
  • I actually shorten it, you can see from my last edit it resolves the issue with the "; else null" which doesn't generate the div if the id doesn't match. – Globality May 06 '21 at 10:24