Home > Net >  Changes in one Array is affecting other Array in Angular project
Changes in one Array is affecting other Array in Angular project

Time:12-17

I am creating a angular project where i am getting API data which i am displaying to user. It has two components "Navigation" and "NewsBlock" and a service called "newsFetchService". API data is fetched by newsfetch service and used by both components.

NewsFetchService
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { NewsData } from './NewsData';
import { HttpClient,HttpHeaders } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class NewsfetchserviceService {

  //Global variable storing All fetch data
  newsBlockData : NewsData[] = [];
  allNews : NewsData[] = [];

  constructor(
    private http:HttpClient
  ) { }

  private newsFetchURL = 'api/v1/topics';

  getNews() {
    return new Promise((resolve, reject) => {
    this.http.get<NewsData[]>(this.newsFetchURL).subscribe(res => {
    this.allNews = res;
    this.newsBlockData = res;
    resolve(true);
    })
    })
    }

    updateNewsBlock(selectedNews : NewsData){

      this.newsBlockData.length = 0;
       this.newsBlockData.push(selectedNews);
    }
}

navigation.component.ts
import { Component, OnInit } from '@angular/core';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { Observable } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';
import { NewsfetchserviceService } from '../newsfetchservice.service';
import { NewsData } from '../NewsData';
@Component({
  selector: 'app-navigation',
  templateUrl: './navigation.component.html',
  styleUrls: ['./navigation.component.css']
})
export class NavigationComponent implements OnInit{

  sourcesList : NewsData[] = [];
  
  ngOnInit(): void {
    this.showAllSources();
  }

  isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
    .pipe(
      map(result => result.matches),
      shareReplay()
    );

  constructor(private breakpointObserver: BreakpointObserver,private newsfetch: NewsfetchserviceService) {}

  showAllSources():void {
    this.sourcesList = this.newsfetch.allNews;
    /* this.newsfetch.getNews().subscribe(news => this.news = news); */
  }

  updateNewsList(source : NewsData):void{
    console.log('option selected');
    console.log(source);
    this.newsfetch.updateNewsBlock(source);
  }
}

newsBlock.component.ts
import { Component, OnInit } from '@angular/core';
import { NewsData } from '../NewsData';
import { NewsfetchserviceService } from '../newsfetchservice.service';

@Component({
  selector: 'app-newsblock',
  templateUrl: './newsblock.component.html',
  styleUrls: ['./newsblock.component.css']
})
export class NewsblockComponent implements OnInit {

  constructor(private newsfetch: NewsfetchserviceService) { }

  newsBlockData : NewsData[] = [];
  ngOnInit(): void {
    this.getNews();
  }

  getNews():void {
    this.newsBlockData = this.newsfetch.newsBlockData;
    /* this.newsfetch.getNews().subscribe(news => this.news = news); */
  }

}

Now, when user click a field in Navigation component it updates the newsBlockData array in Newsfetchservice. This newsBlockData is used by "newsBlock" component which is correctly updating data based on data changed. Issue i am facing is that updating data within newsBlockData array is also affecting allnews array Data. Any data added or removed from newsBlockData array is also reflected in allnews array even though they are two separate arrays.

I have tried changing approach like trying to use subscriber and promise but getting the same issue. Also tried deep copying and shallow copying but getting the same result

CodePudding user response:

The problem is in the getNews() method. Even though you initialize both properties to point to a separate array:

newsBlockData : NewsData[] = [];
allNews : NewsData[] = [];

In your getNews() method, you point them to the same array:

getNews() {
  return new Promise((resolve, reject) => {
    this.http.get<NewsData[]>(this.newsFetchURL).subscribe(res => {
      this.allNews = res;
      this.newsBlockData = res;
      resolve(true);
    })
  })
}

A shallow copy in this case should be sufficient:

getNews() {
  return new Promise((resolve, reject) => {
    this.http.get<NewsData[]>(this.newsFetchURL).subscribe(res => {
      this.allNews = [...res];
      this.newsBlockData = [...res];
      resolve(true);
    })
  })
}
  • Related