1
votes

With angular if i have smart and dump components, if i have lets say an array in a smart component i need to make an observable out of it to make make the dump component read the input with an async pipe so that if i change the value of the array the detect change works and updated the dumb component. if i use just the array .

pieces = new ReplaySubject<{ item: Piece, index: number }[]>(1);
selectedPieces = new ReplaySubject<{ item: Piece, index: number }[]>(1);
piecesArray: { item: Piece, index: number }[];
selectedPiecesArray: { item: Piece, index: number }[] = [];
removePieces(pieces: { item: Piece, index: number }[]) {
        this.piecesArray = this.piecesArray.concat(...pieces);
        this.selectedPiecesArray = this.selectedPiecesArray.filter(p => pieces.indexOf(p) === -1);
        this.pieces.next(this.piecesArray.sort((a, b) => a.index - b.index));
        this.selectedPieces.next(this.selectedPiecesArray);
    } 

what is the right way to handle this. should i use just observable and subscribe to it every time i need to operate on the value ?

1
Not sure what you are asking for... - Martin Adámek
is it normal to have and array and an observable that keeps the same value the array has just so that when i mutate the array the observable updates the dumb component with the new array data. - bakaou baka
Well as you noted, you need to have the observable to allow proper change detection. You can use async pipe with @Input component binding so the child component will have just simple value, that is probably the best thing to do. Not sure if that is what you are referring in your question or if you mean just usage of async pipe in child component's template. - Martin Adámek
as you said with the async pipe the child component get simple value. but if i have an output from the child component to change the data of the array. should i subscribe in the smart component get value alter it and call subject.next or should i have always an array in the smart and when an out put get triggered from the child i alter the array and call subject.next with the array - bakaou baka
then you need to pass also the observable/subject to it and call next on that... If you do not need to work with the value inside child controller, you can move the usage of async pipe to child template, but that's probably all you can do. You could also move the observable with the whole array so some shared service too. - Martin Adámek

1 Answers

0
votes

As I noted in comments, you could move all of the logic to shared service, that will hold both the array and the observable:

export class DataService {

  pieces = new ReplaySubject<{ item: Piece, index: number }[]>(1);
  selectedPieces = new ReplaySubject<{ item: Piece, index: number }[]>(1);
  piecesArray: { item: Piece, index: number }[];
  selectedPiecesArray: { item: Piece, index: number }[] = [];

  removePieces(pieces: { item: Piece, index: number }[]) {
    this.piecesArray = this.piecesArray.concat(...pieces);
    this.selectedPiecesArray = this.selectedPiecesArray.filter(p => pieces.indexOf(p) === -1);
    this.pieces.next(this.piecesArray.sort((a, b) => a.index - b.index));
    this.selectedPieces.next(this.selectedPiecesArray);
  }

}

export class MyComponent {

  constructor(public dataService: DataService) {}

}

<div>{{ dataService.pieces | async | json }}</div>
<div>{{ dataService.selectedPieces | async | json }}</div>

<a (click)="dataService.removePieces(...)">remove</a>