2

I am trying to get array value from en.json translation file in angular and try to bind it to an object property as shown below code snippet.

typescript code:

  ngOnInit() {
    this.en = {
      dayNamesMin: this.translateSvc
                  .get(['calendar.day_names_min.Sun', 'calendar.day_names_min.Mon', 'calendar.day_names_min.Tue', 'calendar.day_names_min.Wed',
                    'calendar.day_names_min.Thu', 'calendar.day_names_min.Fri', 'calendar.day_names_min.Sat'])
                  .subscribe(translated => {
                    console.log(Object.keys(translated).map(key => translated[key]));
                    return Object.keys(translated).map(key => translated[key]);
                  })
    };
  };

en.json file looks like this:

{
    "calendar" : {
        "day_names_min": {
            "Sun": "SUN",
            "Mon": "MON",
            "Tue": "TUE",
            "Wed": "WED",
            "Thu": "THU",
            "Fri": "FRI",
            "Sat": "SAT"
        }
    }
}

I am using ngx translator service to get the data from en.json file and then subscribe and assign value to dayNamesMin property of this.en object.

When I log the value Object.keys(translated).map(key => translated[key]); value in console, I am getting the proper array ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"]. But it is not binding to the object property dayNamesMin.

Can someone please help here ?

1 Answers1

1

When you're dealing with asynchronous data using observables, it's better to assign values inside it's subscription instead of trusting that the variable will be assigned when it's accessed. In your case, you could do something like the following

ngOnInit() {
  this.translateSvc.
    .get([
      'calendar.day_names_min.Sun', 
      'calendar.day_names_min.Mon', 
      'calendar.day_names_min.Tue', 
      'calendar.day_names_min.Wed',
      'calendar.day_names_min.Thu', 
      'calendar.day_names_min.Fri', 
      'calendar.day_names_min.Sat'
    ])
    .subscribe(translated => {
      this.en = {
        dayNamesMin: Object.keys(translated).map(key => translated[key])
      };
    });
}

Now you have an idea that the this.en variable isn't assigned value until the this.translateSvc.get() observables emits. So you need to remember that this.en is asynchronous when it's accessed.

More info on async data here.


Or say if you only want to use the this.en variable in the template to display the values, you could map the output from this.translateSvc.get() using RxJS map operator and use Angular async pipe.

Controller

en$: Observable<any>;

ngOnInit() {
  this.en$ = this.translateSvc.     // <-- assign the observable
    .get([
      'calendar.day_names_min.Sun', 
      'calendar.day_names_min.Mon', 
      'calendar.day_names_min.Tue', 
      'calendar.day_names_min.Wed',
      'calendar.day_names_min.Thu', 
      'calendar.day_names_min.Fri', 
      'calendar.day_names_min.Sat'
    ])
    .pipe(       // <-- transform the response here
      map(translated => ({ dayNamesMin: Object.keys(translated).map(key => translated[key]) }))
    );
}

Template

<ng-container *ngIf="(en$ | async) as en">
  {{ en.dayNamesMin | json }}
  {{ en.dayNamesMin[0] }}
  ...
  <p *ngFor="let day of en.dayNamesMin">
    {{ day }}
  </p>
</ng-container>

Update: Use with PrimeNg calendar

As shown in the second variant, use RxJS map operator to transform it to the required object format and use it as the input in the HTML template.

<ng-container *ngIf="(en$ | async) as en">
  <p-calendar 
    dateFormat="dd/mm/yy" 
    [(ngModel)]="value" 
    [locale]="en">   <!-- use `en` from the async pipe -->
  </p-calendar>
</ng-container>
ruth
  • 29,535
  • 4
  • 30
  • 57
  • My requirement is that I am using primeng calendar component where I need to send [locale] object to primeng calendar as shown below. Here I need to read the value to en object from translation file. Hope now its clear – shrinivas desai Aug 21 '20 at 14:56
  • That does not work. I am not getting any data with this change. Do you mind connecting with me to help on this? Help will be appreciated. – shrinivas desai Aug 21 '20 at 15:19
  • @shrinivasdesai: Did you try `{{ en.dayNamesMin | json }}` inside the ``? What was the result? It should display atleast something when the `en$` observable emits. If not, the other option would be the first variant that I've showed. Either way you need to check if the `this.en` variable is defined before binding it. In the first variant you could something like `...`. If it still doesn't work please try to create a minimal working example in Stackblitz. – ruth Aug 21 '20 at 15:24