Angular removing elements from a list shared with a service - javascript

this problem is driving me crazy.
I have an array defined within a service, which is used in 3 other components:
This is the service, file products.service.ts (notice the product array of Products)
import { Injectable } from '#angular/core';
import { ​​HttpClient } from '#angular/common/http';
import { Product } from './../models/Product';
import { ProductForm, productFormToProduct } from './../models/ProductForm';
// #Injectable({
// providedIn: 'root'
// })
const apiUrl = 'http://localhost:3000/products';
#Injectable()
export class ProductsService {
public products: Product[] = [];
constructor(private http: HttpClient) {}
getProducts() {
return this.http.get(apiUrl)
}
deleteProduct(p: Product) {
// this.products = this.products.filter(prod => prod.id !== p.id);
const i = this.products.indexOf(p);
this.products.splice(i,1);
return this.http.delete(apiUrl + "/" + p.id)
}
storeNewProduct(pf: ProductForm) {
const idList = this.products.map((x) => {return x.id});
const i = Math.max(...idList) + 1;
const p = productFormToProduct(pf);
p.id = i;
this.products.push(p);
return this.http.post(apiUrl, p)
}
}
This is the component where i subscribe to getProducts, and fill the array (file products.component.ts):
import { Component, OnInit } from '#angular/core';
import { ProductsService } from '../../shared/services/products.service';
import { Product } from '../../shared/models/Product';
#Component({
selector: 'app-products',
templateUrl: './products.component.html',
styleUrls: ['./products.component.scss']
})
export class ProductsComponent implements OnInit {
products: Product[] = [];
searchText: string = "";
constructor(private productsService: ProductsService) {}
ngOnInit(): void {
this.productsService.getProducts()
.subscribe((data: Product[]) => {
this.productsService.products = data;
this.products = this.productsService.products;
})
}
}
And this is the component where i subscribe to deleteProduct (file product-card.component.ts):
import { Component, Input, OnInit } from '#angular/core';
import { ProductsService } from '../../services/products.service';
import { Product } from './../../models/Product';
#Component({
selector: 'app-product-card',
templateUrl: './product-card.component.html',
styleUrls: ['./product-card.component.scss']
})
export class ProductCardComponent implements OnInit {
constructor(private productsService: ProductsService) {}
ngOnInit(): void {
}
#Input() product: Product
public buttonDeleteFunction() {
this.productsService.deleteProduct(this.product).subscribe();
}
}
The problem is, when i click on some delete product button, i have this weird behaviour:
Before click:
After click:
Here is the products.component.html file:
<div class="products__header">
<h3 class="products__heading">
Listado de productos ({{ products.length }})
</h3>
<input
class="products__search"
placeholder="Buscador"
type="search"
[(ngModel)]="searchText"
/>
</div>
<p *ngFor="let p of products">{{ p.name }}</p>
<p>{{ products }}</p>
<div class="products__list">
<app-product-card
*ngFor="let p of products | filterNames: searchText"
[product]="p"
></app-product-card>
</div>
Why do i get the expected behaviour in only two of the four places where i use the products list?
I know i can use an Output to manually remove the item from the list when i click the button, but i have been told that services are used instead of Inputs/Outputs when i want to share between multiple components, so i'd rather not use an Output for this

When you use your approach with common data on service layer then a common pitfall is that Angular does not detect the changes that affect your component. In that case you must inform your component for those changes using an emmiter.
Use an emmiter on service
productUpdated :EventEmitter = new EventEmitter();
deleteProduct(p: Product) {
// this.products = this.products.filter(prod => prod.id !== p.id);
const i = this.products.indexOf(p);
this.products.splice(i,1);
this.productUpdated.emit(this.products);
return this.http.delete(apiUrl + "/" + p.id)
}
And then listen for that change ProductsComponent
export class ProductsComponent implements OnInit {
products: Product[] = [];
searchText: string = "";
constructor(private productsService: ProductsService) {}
ngOnInit(): void {
this.productsService.getProducts()
.subscribe((data: Product[]) => {
this.productsService.products = data;
this.products = this.productsService.products;
})
this.productsService.productUpdated.subscribe( (data) => {
this.products = data;
});
}

Related

error TS2559: Type 'BookInterface[]' has no properties in common with type 'BookInterface'

Dear I am developing a page with Angular 7 and I am presented with the error TS2559: Type 'BookInterface[]' has no properties in common with type 'BookInterface', I have changed the code but I still can not find the solution, I leave the code below, the error is thrown in the method getListBooks(): this is my file list-books.component.ts
import { BookInterface } from './../../../models/book';
import { DataApiService } from './../../../services/data-api.service';
import { Component, OnInit } from '#angular/core';
import {NgForm} from '#angular/forms';
#Component({
selector: 'app-list-book',
templateUrl: './list-book.component.html',
styleUrls: ['./list-book.component.css']
})
export class ListBookComponent implements OnInit {
constructor(private dataApi: DataApiService) { }
private books: BookInterface = {};
ngOnInit() {
this.getListBooks();
}
getListBooks() {
this.dataApi.getAllBooks().subscribe(books => {
this.books = books;
});
}
onDelete() {
console.log('LIBRO ELIMINADO');
}
}
I also leave the code of my data-api.service.ts from where I call the interface
import { map } from 'rxjs/operators';
import { Observable } from 'rxjs/internal/Observable';
import { Injectable } from '#angular/core';
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from '#angular/fire/firestore';
import { BookInterface } from '../models/book';
#Injectable({
providedIn: 'root'
})
export class DataApiService {
constructor(private afs: AngularFirestore) {
this.bookCollecction = afs.collection<BookInterface>('books');
this.books = this.bookCollecction.valueChanges();
}
private bookCollecction: AngularFirestoreCollection<BookInterface>;
private books: Observable<BookInterface[]>;
private bookDoc: AngularFirestoreDocument<BookInterface>;
private book: Observable<BookInterface>;
getAllBooks() {
return this.books = this.bookCollecction.snapshotChanges()
.pipe(map( changes => {
return changes.map( action => {
const data = action.payload.doc.data() as BookInterface;
data.id = action.payload.doc.id;
return data;
});
}));
}
// metodo que trae un libro a traves de su id
getOneBook(idBook: string) {
this.bookDoc = this.afs.doc<BookInterface>(`books/${idBook}`);
return this.book = this.bookDoc.snapshotChanges().pipe(map(action => {
if (action.payload.exists === false){
return null;
} else {
const data = action.payload.data() as BookInterface;
data.id = action.payload.id;
return data;
}
}));
}
addBook(book: BookInterface): void {
this.bookCollecction.add(book);
}
updateBook(book: BookInterface): void {
let idBook = book.id;
this.bookDoc = this.afs.doc<BookInterface>(`books/${idBook}`);
this.bookDoc.update(book);
}
deleteBook(idBook: string): void {
this.bookDoc = this.afs.doc<BookInterface>(`books/${idBook}`);
this.bookDoc.delete();
}
}
The version of typescript that I am currently using is Version 2.7.2, but also update it without solving the problem
You need to change the following:
private books: BookInterface = {};
to:
private books: BookInterface[] = [];

Angular 7 - Calling a function inside of a sibling component after sending an Output() from the sibling

I have three components. A parent component (dashboard.component.ts) which houses two siblings (poll-form.component.ts and poll.component.ts). One of the siblings, poll-component sends an Output() back to the parent called (editEvent)="editPoll($event)". When this Output() is sent I'd like that to trigger a function inside of the other sibling poll-form.component instead of triggering the function in the parent dashboard.component. What's the correct way of doing this?
My current implementation "sort of" works. It fires the function in the parent and then the parent imports the component and calls the function in the sibling component. The issue, however, is that sibling component skips the ngOnInit() and doesn't have access to the component variables needed within the function.
Ultimately what I'm trying to do is break out the form into its own component but the act of opening the form is triggered by a sibling component.
dashboard.component.html
<div class="page">
<div style="margin-bottom: 20px; margin-right: 20px; text-align: left;">
<button type="button" (click)="showCreateModal()" pButton icon="pi pi-check" label="Create Poll"></button>
</div>
<div *ngFor="let pollId of pollIds" style="display: inline-block;">
<app-poll [pollKey]="pollId" (editEvent)="editPoll($event)" (deleteEvent)="deletePoll($event)"></app-poll>
</div>
</div>
<div *ngIf="displayCreateModal">
<app-poll-form [type]="'create'" (closeEvent)="closeModal($event)"></app-poll-form>
</div>
<div *ngIf="displayEditModal">
<app-poll-form [type]="'edit'" (closeEvent)="closeModal($event)"></app-poll-form>
</div>
poll.component.ts
import { Component, OnInit, Input, Output, EventEmitter } from '#angular/core';
import * as Chart from 'chart.js';
import { Observable } from 'rxjs';
import { FirebaseService } from '../services/firebase.service';
import { first } from 'rxjs/operators';
import { CardModule } from 'primeng/card';
import { AngularFireAuth } from '#angular/fire/auth';
#Component({
selector: 'app-poll',
templateUrl: './poll.component.html',
styleUrls: ['./poll.component.scss']
})
export class PollComponent implements OnInit {
poll:any;
#Input()
pollKey: string;
#Output()
editEvent = new EventEmitter<string>();
constructor(private firebaseService: FirebaseService, private afAuth: AngularFireAuth) { }
ngOnInit() {
this.firebaseService.getPoll(this.pollKey).subscribe(pollDoc => {
if (!pollDoc.payload.exists) {
return;
}
const pollData:any = pollDoc.payload.data();
this.poll = {
id: pollDoc.payload.id,
helperText: pollData.helperText,
pollType: pollData.pollType,
scoringType: pollData.scoringType,
user: pollData.user
};
}
edit() {
this.editEvent.emit(this.poll);
}
}
poll-form.component.ts
import { Component, OnInit, Input, Output, EventEmitter } from '#angular/core';
import { DialogModule } from 'primeng/dialog';
import { DropdownModule } from 'primeng/dropdown';
import { AutoCompleteModule } from 'primeng/autocomplete';
import { SelectButtonModule } from 'primeng/selectbutton';
import { FirebaseService } from '../services/firebase.service';
import nflPlayers from '../../assets/data/players-nfl.json';
import nflPollTypes from '../../assets/types/poll-types-nfl.json';
import nflScoringTypes from '../../assets/types/scoring-types-nfl.json';
#Component({
selector: 'app-poll-form',
templateUrl: './poll-form.component.html',
styleUrls: ['./poll-form.component.scss']
})
export class PollFormComponent implements OnInit {
title:string;
btnLabel:string;
selectedScoringType:any;
choices:any;
selectedPollType:any;
selectedPollKey:any;
displayEditModal:boolean = false;
displayCreateModal:boolean = false;
filteredPlayersMultiple: any[];
displayModal:boolean = true;
nflPlayers:any = nflPlayers.Players;
nflPollTypes:any = nflPollTypes.types;
nflScoringTypes:any = nflScoringTypes.types;
activePlayers:any;
#Input()
type: string;
#Output()
closeEvent = new EventEmitter<string>();
constructor(
private firebaseService: FirebaseService
) { }
ngOnInit() {
this.initFormDefaults();
}
initFormDefaults() {
this.choices = [[],[]];
this.selectedScoringType = this.nflScoringTypes[0];
this.selectedPollType = this.nflPollTypes[0];
if (this.type == "create") {
this.btnLabel = "Create";
this.title = "Create Poll";
} else {
this.btnLabel = "Update";
this.title = "Edit Poll";
}
// Filter out active NFL players
this.activePlayers = this.nflPlayers.filter(player => player.active == "1");
}
editPoll(poll) {
this.type = "edit"
this.activePlayers = this.nflPlayers.filter(player => player.active == "1");
this.selectedPollKey = poll.id;
// Set scoring type
this.selectedScoringType = this.nflScoringTypes.find((type) => {
return type.code == poll.scoringType
});
// Set poll type
this.selectedPollType = this.nflPollTypes.find((type) => {
return type.code == poll.pollType
});
// Populate edit modal with properly formatted Player objects
for (let i=0; i < poll.choices.length; i++) {
this.choices[i] = poll.choices[i].players.map((choicePlayer:any) => {
return this.activePlayers.find(player => player.playerId == choicePlayer.id);
});
}
}
}
dashboard.component.ts
import { Component, OnInit } from '#angular/core';
import { AngularFireAuth } from '#angular/fire/auth';
import { first } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { PollFormComponent } from '../poll-form/poll-form.component';
#Component({
providers: [PollFormComponent],
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.scss']
})
export class DashboardComponent implements OnInit {
displayEditModal:boolean = false;
constructor(
private pollFormComponent: PollFormComponent
) { }
ngOnInit() {
}
editPoll(poll) {
this.displayEditModal = true;
this.pollFormComponent.editPoll(poll);
}
}

Passing data between components using a service Angular

There are many examples around the web on this subject but none of them helped me. This is the scenario: I've got 2 components and a service. The two components aren't parent/children but are 2 independent components. One of them has a list of names, the other should load a table when one of the names is clicked. This is my home.html with both components
<div class="material-docs-app">
<div class="docs-primary-header">
<h1>Yep!</h1>
</div>
<div fxLayout="row" fxLayout.xs="column" class="component-layout-body">
<app-heroes-sidenav></app-heroes-sidenav>
<app-heroes-table #heroesTable fxFlex="1 2 calc(15em + 20px)" style="width: 100%"></app-heroes-table>
</div>
</div>
Heroes sidenav component:
<div *ngIf="loadingData == true">
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
</div>
<nav *ngIf="loadingData == false">
<p *ngFor="let item of heroesNames.results let i = index" [attr.data-index]="i">
<button mat-button (click)="getHero(i)">
{{item.name}}
</button>
</p>
</nav>
On click getHero() is called correctly. This is the sidenav component ts:
import { Component, OnInit, Input } from '#angular/core';
import {SwCharactersServiceService} from '../sw-characters-service.service';
import {HeroesTableComponent} from '../heroes-table/heroes-table.component';
#Component({
selector: 'app-heroes-sidenav',
templateUrl: './heroes-sidenav.component.html',
styleUrls: ['./heroes-sidenav.component.css']
})
export class HeroesSidenavComponent implements OnInit {
heroesNames: any;
heroData:any;
loadingData = true;
#Input() heroesTable: HeroesTableComponent;
constructor(private _swService: SwCharactersServiceService) { }
ngOnInit() {
this.getHeroes();
}
getHeroes() {
this._swService.getCharacters().then(result => {
this.loadingData = false;
this.heroesNames = result;
});
}
getHero(index) {
this._swService.getHero(index);
}
}
and this is the service:
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import 'rxjs/add/operator/map'
import {Observable} from 'rxjs/Observable';
#Injectable({
providedIn: 'root'
})
export class SwCharactersServiceService {
param:any;
constructor(private http: HttpClient) { }
getCharacters(): Promise<any[]> {
return this.http.get<any[]>("https://swapi.co/api/people/")
.toPromise()
.then(result => result)
.catch(this.handleError);
}
getHero(index): Observable<any>{
console.log(index);
let headers = new HttpHeaders();
headers.append('Content-Type', 'application/json');
return this.http.get("https://swapi.co/api/people/" + index, {
headers: headers
}).map(res => res );
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error); // for demo purposes only
return Promise.reject(error.message || error);
}
}
I can correctly see the console.log(index) but the request doesn't work. There is no request initiated in chrome console network tab.
This is the component with the table:
import { Component, OnInit, Input, Output, EventEmitter } from '#angular/core';
import { Subscription } from 'rxjs/Subscription';
import {SwCharactersServiceService} from '../sw-characters-service.service';
#Component({
selector: 'app-heroes-table',
templateUrl: './heroes-table.component.html',
styleUrls: ['./heroes-table.component.css']
})
export class HeroesTableComponent implements OnInit {
loadingData = true;
heroData :any;
subscription: Subscription;
constructor(private _swService: SwCharactersServiceService) {
this.subscription = this._swService.getHero(1).subscribe(result => { this.heroData = result; });
console.log(this.heroData);
}
ngOnInit() {
}
ngOnDestroy() {
// unsubscribe to ensure no memory leaks
this.subscription.unsubscribe();
}
}
There are 2 problems now:
1) As you can see I wrote this._swService.getHero(1) without passing a dynamic param. How does it work? How can I pass the correct index?
2) The service doesn't fire and I haven't got any result.
Is there any other way to do that?
Thanks.
you can use BehaviourSubject to pass the index value and send the query request as the list is cliked
in the service
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
public index: BehaviorSubject<number> = new BehaviorSubject<number>(null);
in the sidenav component
getHero(index) {
this._swService.index.next(index);
}
in the hero table component
ngAfterViewInit(){
this._swService.index.subscribe(index=>{
if(index){
this._swService.getHero(index).subscribe(result => { this.heroData = result; });
}
})
}
You missed to subscribe to _swService.getHero(). If not subscribed to a method which returns an Observable, then it wont be invoked.
getHero(index) {
this._swService.getHero(index).subscribe(
(resp) => {
// manipulate your response here
console.log(resp);
},
(err) => {}
);
}

Shared service example Angular 5

I know this question has been asked several times, but problem is that nobody tried to make a some fiddle or show results of code. This is what i have, i need to update values in other component based on value in some other component, but that is not just value,I have call function again in some other component.
I have some component that goes to database and update values, on second hand I have other component that read those values from database from service.
This is example of my code
tasks.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { environment } from '../../environments/environment';
import { Tasks } from './tasks';
#Injectable()
export class TasksProvider {
constructor(private http: HttpClient) { }
createNewTask(name: Name) : Observable<any> {
return this.http.post(environment.apiUri + 'tasks', { name, finished: false },
{ responseType: 'text' });
}
updateTask(id: Id, name: Name, finished: boolean) : Observable<any> {
return this.http.put(environment.apiUri + 'tasks/' + id, { name, finished },
{ responseType: 'text' });
}
getAllTasks(): Observable<Tasks[]> {
return this.http.get(environment.apiUri + 'tasks')
.map<any, Tasks[]>(data => data.map(Tasks.fromObject));
}
}
app.component.html
<app-tasks-list></app-tasks-list>
<app-tasks-add-new></app-tasks-add-new>
As you may see I have not child components, that is my main problem
tasks-list.component.ts
import {Component} from '#angular/core';
import { Tasks } from '../services/tasks';
import { TasksProvider } from '../services/tasks.service';
#Component({
selector: 'app-tasks-list',
templateUrl: './tasks-list.component.html',
styleUrls: ['./tasks-list.component.scss']
})
export class TasksListComponent {
tasks: Array<Tasks>;
constructor(private tasksProvider: TasksProvider) { }
ngOnInit() {
this.getTasksList();
}
displayedColumns: string[] = ['id', 'name', 'finished'];
private getTasksList() {
this.tasksProvider.getAllTasks()
.subscribe(tasks => {
this.tasks = tasks;
});
}
public updateCheckboxValue(id: number, name: string, event: any){
this.tasksProvider.updateTask(id, name, event.checked).subscribe(
result => {},
() => {
alert('Something went wrong');
})
}
}
tasks-add-new.component.ts
import { Component, OnInit, Inject } from '#angular/core';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '#angular/material';
import { Tasks } from '../services/tasks';
import { TasksProvider } from '../services/tasks.service';
export interface DialogData {
name: string;
}
#Component({
selector: 'app-tasks-add-new',
templateUrl: './tasks-add-new.component.html',
styleUrls: ['./tasks-add-new.component.scss']
})
export class TasksAddNewComponent implements OnInit {
ngOnInit() {
}
constructor(public dialog: MatDialog, private tasksProvider: TasksProvider) {}
openDialog(): void {
const dialogRef = this.dialog.open(TasksAddNewDialog, {
width: '250px',
data: {name: this.animal}
});
dialogRef.afterClosed().subscribe(result => {
this.name = result
this.tasksProvider.createNewTask(this.name).subscribe(
result => {},
() => {
alert('Something went wrong');
})
}
}
}
#Component({
selector: 'tasks-add-new-dialog',
templateUrl: 'tasks-add-new-dialog.html'
})
export class TasksAddNewDialog {
constructor(
public dialogRef: MatDialogRef<TasksAddNewDialog>,
#Inject(MAT_DIALOG_DATA) public data: DialogData) {}
onNoClick(): void {
this.dialogRef.close();
}
}
You see now when i call function in tasks-add-new.component.ts like
this.tasksProvider.createNewTask(this.name).subscribe(
result => {},
() => {
alert('Something went wrong');
})
I need to call again function in tasks-list.component.ts
private getTasksList() {
this.tasksProvider.getAllTasks()
.subscribe(tasks => {
this.tasks = tasks;
});
}
Does any body have idea how i can do that the best practice?
On of the possible approach is to use Subjects.
1) Store task list on the service and provide subscribable Subject
private tasks: Array<Task>;
public $tasks: BehaviorSubject<Array<Task>>;
constructor(private http: HttpClient) {
this.$tasks = new BehaviorSubject([]);
...
}
getAllTasks() {
this.http.get(environment.apiUri + 'tasks')
.subscribe(data => {
this.tasks = data;
this.$tasks.next(this.tasks);
});
}
updateTask(params) {
this.http.post(/* params */).subscribe((task) => {
this.tasks = this.tasks.map(t => t.id !== task.id ? t : task);
this.$tasks.next(this.tasks);
});
}
createTask(...) {
// again, do a request, update this.tasks and call $tasks.next
...
}
2) Make one service Subject subscription on the component instead of multiple service methods Observable listeners and update component's list automatically each time the service source has been changed
tasks: Array<Tasks>;
constructor(private tasksProvider: TasksProvider) {
this.tasksProvider.$tasks.subscribe(tasks => this.tasks = tasks);
}
ngOnInit() {
this.tasksProvider.getAllTasks();
}
public updateCheckboxValue(id: number, name: string, event: any){
this.tasksProvider.updateTask(id, name, event.checked);
}

Triggering change detection when i use service communication

So I have two not related components and I'm trying to communicate between them using a service and a BehaviorSubject. Everything is cool, data is exchanged, but when i call the service from one of the components, it doesn't trigger change detection on the other component.
So to show what I'm talking about in code:
The service:
import {Injectable, Optional, EventEmitter} from '#angular/core';
import {Http} from '#angular/http';
import 'rxjs/add/operator/map';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { forEach } from '#angular/router/src/utils/collection';
#Injectable()
export class SbkService {
items: any = [];
private _itemsSource = new BehaviorSubject<any>(0);
items$ = this._itemsSource.asObservable();
constructor (
private _localStorageService: LocalStorageService
) {}
storeSelection(item) {
this.items.push(item);
this.setLocalStorage();
}
removeSelection(selectionId) {
for (var i = this.items.length-1; i >= 0; i--) {
if (this.items[i].selectionId == selectionId)
this.items.splice(i, 1);
}
this.setLocalStorage();
return true;
}
getLocalStorage() {
this.items = this._localStorageService.get('items');
this._itemsSource.next(this.items);
return this.items;
}
setLocalStorage() {
this._localStorageService.set('items', this.items);
this._itemsSource.next(this.items);
return true;
}
}
Component 1:
import { Component, OnInit } from '#angular/core';
import { SbkService } from '../../services/sbk.service'
import {Subscription} from 'rxjs/Subscription';
#Component({
selector: 'app-right-sidebar',
template: `<ul>
<li *ngFor="let selection of selections">
{{selection.name}}
<span class="cutom-btn" (click)="remove(selection.selectionId)">
delete
</span>
</li>
</ul>`,
styles: []
})
export class RightSidebarComponent implements OnInit {
selections: any = [];
subscription:Subscription;
constructor (
private _sbkService: SbkService
) {
}
ngOnInit() {
this.subscription = this._sbkService.items$
.subscribe(selections => {
this.selections = selections })
this._sbkService.getLocalStorage();
}
ngOnDestroy() {
// prevent memory leak when component is destroyed
this.subscription.unsubscribe();
}
remove(selectionId) {
this._sbkService.removeSelection(selectionId);
}
}
Component 2:
import { Component, ViewChild, ElementRef } from '#angular/core';
import 'rxjs/add/operator/map';
import {forEach} from '#angular/router/src/utils/collection';
import {SbkService} from '../services/sbk.service'
#Component({
selector: 'app-match-table',
template: `
<div (click)="addItem('mumble', 1)">Add mumble</div>
<div (click)="addItem('ts', 2)">Add ts</div>
<div (click)="addItem('discord', 3)">Add discord</div>
`,
styles: []
})
export class MatchTableComponent {
constructor(
private _sbkService: SbkService
) {}
//Place a bet in the betslip
public addItem = (name, selectionId) => {
item: Object = {};
item.selectionId = selectionId;
item.name = name;
this._sbkService.storeSelection(item);
}
}
So, when I click on a div from component 2 (MatchTableComponent) it updates the selections array in component 1 (RightSideBarComponent) but doesn't trigger a change detection, so the sorted list doesn't get updated until i refresh the page. When i click on delete from RightSideBarComponent template, it updates the selections array and triggers the change detection.
How can I make this work? I tried subscribing to an event from SbkService in the AppComponent and from there triggering the setLocalStorage from SbkService, but no luck...
If I'm not wrong, you should set the next "sequence" on your Observable "items" through your BehaviourSubject.
Could you modify and try this?:
storeSelection(item){
const itemsAux = this._itemsSource.getValues();
itemsAux.push(item);
this._itemsSource.next(itemsAux);
}
setLocalStorage(){
this._localStorageService('items', this._itemsSource.getValues();
return true;
}

Categories