I'm trying to have a navbar with categories and a home component that also uses those categories. I don't want to have to call my API twice and I will use that same categories variable in other places. I tried doing the following:
Data Service
This service gets the data from the api url and returns the subscribable object.
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class DataService {
api_url: string = "https://apiurlhere";
categories: Object;
constructor(private http: HttpClient) { }
getCategories(){
return this.http.get(this.api_url+'/categorylisting/?z=1');
}
getZones(){
return this.http.get(this.api_url+'/zones/');
}
}
Navbar Component
The Navbar component makes use of the categories variable to show the different options, this works fine since the subscribe is in this component.
import { Component, OnInit } from '@angular/core';
import { trigger, state, transition, animate, style } from '@angular/animations';
import { DataService } from '../data.service';
@Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.scss'],
animations: [
trigger('slideInOut', [
state('in', style({
overflow: 'hidden',
height: '*'
})),
state('out', style({
overflow: 'hidden',
height: '0px'
})),
transition('in => out', animate('400ms ease-in-out')),
transition('out => in', animate('400ms ease-in-out'))
])
]
})
export class NavbarComponent implements OnInit {
categories: Object;
constructor(private data:DataService) { }
ngOnInit() {
this.data.getCategories().subscribe( data => {
this.categories = data
for(let category in this.categories){
this.categories[category].productsOpen='out';
for(let product in this.categories[category].product){
this.categories[category].products[product].active = false;
}
}
this.data.categories = this.categories;
});
}
openProducts(index){
this.categories[index].productsOpen = this.categories[index].productsOpen === 'out' ? 'in' : 'out';
}
setActiveProduct(index, productIndex){
for(let category in this.categories){
for(let product in this.categories[category].products){
this.categories[category].products[product].active = false;
}
}
this.categories[index].products[productIndex].active = true;
}
}
Home Component
My Home component also makes use of the categories variable, so I want to know how I can get it here since it is always undefined even if it changes in the service.
import { Component, OnInit } from '@angular/core';
import { DataService } from '../data.service';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
categories: Object;
constructor(private data:DataService) { }
ngOnInit() {
this.categories = this.data.categories;
}
}
Am I doing this right? I'm used to react and redux and in there the render method would run every time a setState was called to change the state, when does angular know when the component's variables have changed? I just want to save a global variable with my data so I can reuse it without calling the API every time. Thank You.
You can cache the observable in your service like:
export class DataService {
someProperty;
api_url: string = "https://apiurlhere";
categories: Object;
constructor(private http: HttpClient) { }
getCategories(){
if(!this.someProperty) {
this.someProperty = this.http.get(this.api_url+'/categorylisting/?z=1');
}
return this.someProperty;
}
}
You can also go for angular Http interceptors else you can also opt for rxjs operator shareReplay
You could try calling your API in the constructor of the DataService
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class DataService {
api_url: string = "https://apiurlhere";
categories: Object;
constructor(private http: HttpClient) {
this.getCategories().subscribe(data => this.categories = data);
}
getCategories(){
return this.http.get(this.api_url+'/categorylisting/?z=1');
}
getZones(){
return this.http.get(this.api_url+'/zones/');
}
}
and then just get the categories in the NavBar component just as you did in the Home component.
ngOnInit() {
this.categories = this.data.categories;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.