Angular - Access values of object stored in array of objects inside template

10,343

Ideally, the property name:

{ ..., name: [{ "pl": "Tekst po polsku" }, { "en": "Text in english" }] },

Would have the format of not an array of objects, but an object:

{ ..., name: {"pl": "Tekst po polsku", "en": "Text in english"} },

Then you could simply use in your template:

<span>{{ settingsTab.name[language] }}</span>

Which is a constant-time lookup (just getting a property in an object).



Now, if you can't change the format of name, I'd use a method instead of those nested ng-containers:

export class MyComponent {
  ...
  lang(names: [any], language: string) {
    return (names.find(lang => lang[language]) || {})[language]
  }
  ...
}

And use it like:

<span>{{ lang(settingsTab.name, language) }}</span>

Of course, you can call lang whatever you see fit. Just notice this alternative has O(n) complexity, due to find having to iterate the name array. This probably won't impact the performance of you application at all, but I thought you should know. In the current format of the name, there is no quicker way here.

Demo: https://stackblitz.com/edit/angular-c5wzbk?file=src/app/app.component.ts

Share:
10,343
Ashiv3r
Author by

Ashiv3r

Updated on June 22, 2022

Comments

  • Ashiv3r
    Ashiv3r about 2 years

    I've got a single class as below:

    export class SettingsTab {
      id: number;
      class: string;
      name: Object = {};
    }
    

    Also I mock it into simple array:

    export const SETTINGSTABS: SettingsTab[] = [
      { id: 1, class: 'classOne', name: [{ "pl": "Tekst po polsku" }, { "en": "Text in english" }] },
      { id: 2, class: 'classTwo', name: [{ "pl": "Tekst po polsku" }, { "en": "Text in english" }] },
      { id: 3, class: 'classThree', name: [{ "pl": "Tekst po polsku" }, { "en": "Text in english" }] }
    ];
    

    Now I would like to access certain value of name object in my template depending on which language I currently use. I get info about current language from localStorage as shown below:

    language = localStorage.getItem('currentLang') != null ? localStorage.getItem('currentLang').replace("'", "") : "pl";
    

    I managed to achieve it by code listed below:

    <ng-container *ngFor="let name of settingsTab.name">
      <ng-container *ngFor="let key of ObjectKeys(name)">
        <span *ngIf="key == language">{{ name[key] }}</span>
      </ng-container>
    </ng-container>
    

    ObjectKeys are defined in my component as:

    ObjectKeys = Object.keys;
    

    But my question is there any easiest way to achieve what I want to do? Don't like two ng-components with *ngFor inside them. Also would like to achieve it in the most optimized way.

  • Ashiv3r
    Ashiv3r over 6 years
    Thaks! I can change the format of name property, so I went that way and it's working like a charm :)