Home > Blockchain >  Angular : declaring and assigning a variable in html template
Angular : declaring and assigning a variable in html template

Time:09-24

I know that the question has already asked on Stackoverflow but the proposed solutions doesn't work.

I need to loop into a list containing categories and items. I want to display only one time the category so I need to test if the category is same that the previous one. If it's the same I don't display it but if not I display the new category. Therefore I want to declare a variable to store the current category name.

Is it possible? If not how can I do to test previous category and new one?

Thanks

Edit : My method to get datas :

getMenuByTruck = () =>{
    const id: string = this.activeRoute.snapshot.params['id'];
    const apiMenu: string = environment.apiAddress   'TruckMenu/'   id;

    this.repository.getData(apiMenu)
    .pipe(finalize(() => {
      this.updateTruckName();
    }))
      .subscribe(response => {
        this.menu = response as Menu[];
      },
      (error) =>{
        this.errorHandler.handleError(error);
        this.errorMessage = this.errorHandler.errorMessage;
      })
}

and my loop into html code :

<div class="title" *ngFor="let m of menu">
    <h3>{{m.foodCategory?.description}}</h3>
</div>

CodePudding user response:

You can create a new object type variable that will have items from original data with unique categories as key.

Suppose we have original data as

originalData = [
    { category: 1, item: 'Jan' },
    { category: 2, item: 'Sarah' },
    { category: 1, item: 'Tom' },
    { category: 2, item: 'Nina' },
  ];

We will declare a new empty object variable. Using reduce on originalData we will check if there is already an entry in the acc by key as category name. If it is there we will copy all those previous items (values), add a new item to it else we will just pass currentObj as an array.

itemsByCategory = {};

this.itemsByCategory = this.originalData.reduce((acc, currentObj) => {
  acc[currentObj.category] = acc[currentObj.category]
    ? [...acc[currentObj.category], currentObj]
    : [currentObj];
  return acc;
}, {});

getter to iterate itemsByCategory

  get categoryKeys(): string[] {
    return Object.keys(this.itemsByCategory);
  }

In template

<ul *ngFor="let key of categoryKeys">
  <li>
    Category : {{ key }}
    <p *ngFor="let obj of itemsByCategory[key]">
      {{ obj.item }}
    </p>
  </li>
</ul>

Demo

If your menu has category as object then see this

CodePudding user response:

You can just make a an array of unique categories, like this:

const data = [
  { category: 1, item: 'Jan' }, 
  { category: 2, item: 'Sarah' }, 
  { category: 1, item: 'Tom' },
  { category: 2, item: 'Nina'}
];

const cats = [...new Set(data.map(item => item.category))];

console.log(cats)

And then loop over the array of categories, using the value to filter your original data and loop over the filtered result in a nested loop.

const data = [
  { category: 1, item: 'Jan' }, 
  { category: 2, item: 'Sarah' }, 
  { category: 1, item: 'Tom' },
  { category: 2, item: 'Nina'}
];

const cats = [...new Set(data.map(item => item.category))];

cats.forEach(cat => {
  console.log(cat)
  data.filter(x => x.category === cat)
    .forEach(x => console.log(x.item))
})

Example in angular project on Stackblitz.

For your followup questions...

You might want to create a service to get your data to keep the request code out of your component and function:

@Injectable({
  providedIn: 'root'
})
export class MenuService {
  readonly API = environment.apiAddress   'TruckMenu/'

  constructor(
    private http: HttpClient
  ) { }

  getData(id: string): Observable<Menu[]> {
    return this.http.get<Menu[]>(this.API   id)
  }
}

In your component:

menus: Menu[] = []
cats: FoodCategory[] = []

constructor(
  private menuService: MenuService,
  private route: ActivatedRoute,
  ...
) { }

ngOnInit(): void {
  this.menuService.getData(this.route.snapshot.params['id'])
    .subscribe(data => {
      this.menus = data
      this.cats = this.getCats(data)
    })
}
  • Related