Object not update by function in the same service Angular - javascript

I create a function (callPlayerData) for replace data in object (playerData) by data from database.
The function and the object is in the same service :
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
interface PlayerData {
name: string,
level: number,
truc: number,
xp: number,
xp_max: number,
vie: number,
vie_max: number
}
#Injectable()
export class PlayerService {
constructor(private http: Http){
}
playerId = null;
playerData: PlayerData = {
name : "unwn",
level : 5,
truc : 36,
xp: 0,
xp_max: 0,
vie: 0,
vie_max: 0
};
callPlayerData(callback) {
let that = this,
loader = document.getElementById("loader");
loader.style.display = "block";
this.http.post(`api/gameData`, {id : that.playerId})
.subscribe(response => {
let gameData = JSON.parse(response.text()),
item = 0;
for (const key in gameData) {
if (that.playerData[key]) {
that.playerData[key] = gameData[key];
}
item++;
if(item === Object.keys(gameData).length) {
//that.playerData = Object.assign(JSON.parse(response.text()));
console.log(that.playerData);
setTimeout(() => {
loader.style.display = "none";
callback();
}, 400);
}
}
}, error => {
console.log(JSON.stringify(error.json()));
});
}
}
The console.log(that.playerData) at the end of the ForIn return the data updated but I have another console.log() in component.
import { Component, OnInit } from '#angular/core';
import { Http } from '#angular/http';
import { Router } from '#angular/router';
import { PlayerService } from '../../player.service';
#Component({
selector: 'stats-section',
templateUrl: './stats.component.html'
})
export class StatsComponent implements OnInit {
constructor(private http: Http, private router: Router, private player: PlayerService) {
}
ngOnInit() {
console.log(this.player.playerData);
setTimeout(() => {
console.log(this.player.playerData);
}, 1000);
}
}
This console.log() return the initial data of the object and not the data updated by the function.
Any ideas how to get the updated data in my component ?
thanks in advance !

Related

Javascript push function

I want to create simple social media app.I'am working now on part with groups.But I cant filter only groups where some user is member.The code is following
import { Component, OnInit, OnChanges } from '#angular/core';
import { AngularFireDatabase } from '#angular/fire/database';
import { GroupsService } from '../groups.service';
#Component({
selector: 'app-groups',
templateUrl: './groups.component.html',
styleUrls: ['./groups.component.scss']
})
export class GroupsComponent implements OnInit {
uid = localStorage.getItem('uid')
groups: Array<any>;
mygroups: Array<any>;
sgroups;
constructor(private db: AngularFireDatabase, private _groups: GroupsService) {
}
ngOnInit() {
this._groups.getGroups().subscribe((data) => {
this.groups = data;
})
this.loadGroups()
}
search(e) {
this.sgroups = this.groups.find(gr => gr.name.toLowerCase().indexOf(e.target.value.toLowerCase()) > -1)
}
loadGroups() {
this.groups.map(gr => {
this._groups.getGroupMembers(gr.id).subscribe((data: any) => {
data.map(mem => {
if(mem.uid == this.uid) {
this.mygroups.push(gr); //here is the problem
}
})
})
})
}
scrollnav() {
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
}
}
Every help is welcomed.
Thanks a lot!
Problem is in initialization. intialize mygroups like
mygroups: any[] = [];
instead of
mygroups: Array<any>;
You can use forkJoin to fire all of the calls at once and get an array with all the results:
import {forkJoin} from 'rxjs';
...
const requests = this.groups.map(gr => this._groups.getGroupMembers(gr.id));
forkJoin(requests).subscribe((res) => this.mygroups = res);

save and fetch on firebase in angular is not working

Why my movie component is not updating after fetching the data. Also not saving the data if I have added a new movie or made changes in existing movies.
It is just saving and fetching the data which is written in movie.service.ts file. Also the fetched data is not rendering on the movie component.
Data-storage.service
import { Injectable } from '#angular/core';
import { MovieService } from '../movies/movies.service';
import { HttpClient, HttpHeaders, HttpParams, HttpRequest } from '#angular/common/http';
import { Movie } from '../movies/movie.model';
import { Observable} from 'rxjs';
import { map } from 'rxjs/operators';
// import 'rxjs/Rx';
// import 'rxjs/Rx';
#Injectable({
providedIn: 'root'
})
export class DataStorageService {
constructor(private httpClient: HttpClient,
private movieService: MovieService,) { }
storeMovies(): Observable<any> {
const req = new HttpRequest('PUT', 'https://moviepedia-4211a.firebaseio.com/movies.json', this.movieService.getMovies(), {reportProgress: true});
return this.httpClient.request(req);
}
getMovies() {
this.httpClient.get<Movie[]>('https://moviepedia-4211a.firebaseio.com/movies.json', {
observe: 'body',
responseType: 'json'
})
.pipe(map(
(movies) => {
console.log(movies);
return movies;
}
))
.subscribe(
(movies: Movie[]) => {
this.movieService.setMovies(movies);
}
);
}
}
movie.service.ts :
import { Injectable } from '#angular/core';
import {Subject} from 'rxjs';
import { Movie } from './movie.model';
#Injectable()
export class MovieService {
moviesChanged = new Subject<Movie[]>();
private movies: Movie[] = [
new Movie(
'Movie test', 'Movie details', 'https://s18672.pcdn.co/wp-content/uploads/2018/01/Movie-300x200.jpg'
),
new Movie(
'Movie test 2', 'Movie details 2', 'https://s18672.pcdn.co/wp-content/uploads/2018/01/Movie-300x200.jpg'
),
new Movie(
'Movie test 2', 'Movie details 3', 'https://s18672.pcdn.co/wp-content/uploads/2018/01/Movie-300x200.jpg'
)
];
constructor(){}
getMovie(index: number) {
return this.movies[index];
}
getMovies() {
return this.movies.slice();
}
addMovie(movie: Movie) {
this.movies.push(movie);
this.moviesChanged.next(this.movies.slice());
}
updateMovie(index: number, newMovie: Movie) {
this.movies[index] = newMovie;
this.moviesChanged.next(this.movies.slice());
}
deleteMovie(index: number) {
this.movies.splice(index, 1);
this.moviesChanged.next(this.movies.slice());
}
setMovies(movies: Movie[]) {
this.movies = movies;
this.moviesChanged.next(this.movies.slice());
}
}
movie.model.ts
export class Movie {
public name: string;
public description: string;
public imagePath: string;
constructor(name: string, description: string, imagePath: string) {
this.name = name;
this.description = description;
this.imagePath = imagePath;
}
}
movie.component :
import { Component, OnInit, EventEmitter, Output, OnDestroy } from '#angular/core';
import { Movie } from '../movie.model'
import { MovieService } from '../movies.service';
import { Router, ActivatedRoute } from '#angular/router';
import { Subscription } from 'rxjs';
#Component({
selector: 'app-movie-list',
templateUrl: './movie-list.component.html',
styleUrls: ['./movie-list.component.css']
})
export class MovieListComponent implements OnInit, OnDestroy {
subscription: Subscription;
movies: Movie[] = [];
constructor(private movieService: MovieService,
private router: Router,
private route: ActivatedRoute) { }
ngOnInit() {
this.subscription = this.movieService.moviesChanged
.subscribe(
(movies: Movie[]) => {
this.movies = movies;
}
);
this.movies = this.movieService.getMovies();
}
onNewMovie() {
this.router.navigate(['new'], {relativeTo: this.route});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
What can I do save and fetch data which will render on page.
I think the problem with your PUT request is that the url you used expects json but you are sending Movie object. you should send and receive json to this url.
wish it helps ...

How to test Angular httpClient methods inside a promise in jasmine?

I know how to test http with a mock backend, as well as promises. Though I am struggling to find a solution to test http methods in a promise. Any advice will be much appreciated. Here's the function which contain the function with the http method inside the promise:
import { Injectable } from '#angular/core';
import { AbstractControl, FormGroup, FormControl, ValidatorFn, AsyncValidatorFn } from '#angular/forms';
import { Headers, RequestOptions } from '#angular/http';
import { Store } from '#ngrx/store';
import { HttpService, IHttpResponse } from '#mystique/mystique-utils/http';
import { IRootState } from '#mystique/mystique-state/root';
#Injectable()
export class ValidatorsService {
regex: { email: string; password: string } = { email: null, password: null };
constructor(private _http: HttpService, private _store: Store<IRootState>) {
this._store.select('config', 'regex').subscribe(regex => (this.regex = regex));
}
recordExistsOnServer(model: string, lookupField: string, savedValue: string, authToken: string): AsyncValidatorFn {
model += 's';
let validationDebounce;
return (control: AbstractControl) => {
const queryParams = [{ key: lookupField, value: control.value }];
clearTimeout(validationDebounce);
return new Promise((resolve, reject) => {
validationDebounce = setTimeout(() => {
if (control.value === '' || control.value === savedValue) {
return resolve(null);
}
this._http.get$(`/${model}`, authToken, queryParams).subscribe((httpResponse: IHttpResponse) => {
if (!httpResponse.data) {
savedValue = control.value;
}
return !httpResponse.data ? resolve(null) : resolve({ recordExistsOnServer: true });
});
}, 400);
});
};
}
Throws this error: Uncaught TypeError:
_this._http.get$ is not a function at localhost:9876/_karma_webpack_/polyfills.bundle.js:2281
Here is my test cases, the last it() fails:
import { TestBed, inject } from '#angular/core/testing';
import { FormGroup, FormControl } from '#angular/forms';
import { StoreModule, Store } from '#ngrx/store';
import { Observable } from 'rxjs/Observable';
import { HttpService } from '#mystique/mystique-utils/http';
import { HttpServiceStub } from '#mystique/mystique-stubs';
import { ValidatorsService } from './validators.service';
import { rootReducer } from '#mystique/mystique-state/root';
describe('ValidatorsService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
StoreModule.forRoot({
config: rootReducer.config
})
],
providers: [{ provide: HttpService, useClass: HttpServiceStub }, ValidatorsService]
});
});
let service, http, store;
beforeEach(() => {
http = TestBed.get(HttpService);
store = TestBed.get(Store);
service = TestBed.get(ValidatorsService);
});
describe('when checking if a record exists on the server', () => {
let control, result, getSpy;
beforeEach(() => {
getSpy = spyOn(http, 'getAll$');
});
it('returns null if the user types the same value', done => {
control = new FormControl('bob');
result = service.recordExistsOnServer('user', 'username', 'bob', 'token');
result(control)['then'](r => {
expect(r).toEqual(null);
done();
});
});
it('returns null if the user types an empty string', done => {
control = new FormControl('');
result = service.recordExistsOnServer('user', 'username', 'bob');
result(control)['then'](r => {
console.log('r: ' + r)
expect(r).toEqual(null);
done();
});
});
it('returns null if the http call cannot find a record', done => {
getSpy.and.returnValue(Observable.of({ data: null }));
control = new FormControl('bobby');
result = service.recordExistsOnServer('user', 'username', 'bob');
result(control)['then'](r => {
expect(r).toEqual(null);
done();
});
});
});
});
Here is my http.service.ts:
import { Injectable } from '#angular/core';
import { Store } from '#ngrx/store';
import { IRootState } from '#mystique/mystique-state/root';
import { HttpClient, HttpErrorResponse, HttpHeaders, HttpParams } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/retry';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import { IBaseModel } from '#spawntech/xmen-core-domain-models';
export interface IHttpQuery {
key: string;
value: string | number;
}
export interface IHttpResponse {
success: boolean;
status: number;
statusText: string;
message: string;
data?: any | any[];
error?: string;
token?: string;
}
#Injectable()
export class HttpService {
apiBaseUrl: string = null;
httpRetries = 3;
constructor(private _http: HttpClient, private _store: Store<IRootState>) {
this._store.select('config', 'apiBaseUrl').subscribe(url => (url ? (this.apiBaseUrl = url) : this.apiBaseUrl));
}
get$(restUrl: string, authToken: string, queryParams?: IHttpQuery[]): Observable<IHttpResponse> {
if (!restUrl) {
throw new Error('A restful url extension must be supplied');
}
const headers = this._prepareAuthHeader(authToken);
const params = this._prepareQueryParams(queryParams);
console.log('in http service---------------')
return this._http
.get<IHttpResponse>(this.apiBaseUrl + restUrl, { headers, params })
.retry(this.httpRetries)
.catch((response: HttpErrorResponse) => this._handleError(response));
}
}
use HttpClientTestingModule for mock http request
TestBed.configureTestingModule({
imports: [..., HttpClientTestingModule],
providers: [...]
})
in the development of applications, I call the service method which returns a query, then I subscribe () and I already consider successful and erroneous queries in the current component, displaying some notifications to the user
then you can take a query from a function to a separate function and do something like this:
spyOn (service, 'confirmEmail').
       .returnValue (Observable.of (new HttpResponse ({body: '', status: 204}))));

Angular 2 Error while making get request: TS2346: Supplied parameters do not match any signature of call target

I am trying to make a simple get request following the angular docs: https://angular.io/docs/ts/latest/guide/server-communication.html
Still getting this error on line 15 in editor.
return this.http.get(this.heroesUrl)
.map(this.extractData)
Please find full code here:
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
#Injectable()
export class EventListService {
private heroesUrl = '/data.json'; // URL to web API
constructor (private http: Http) {}
getEvents (): Observable<Hero[]> {
return this.http.get(this.heroesUrl)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response): Hero[] {
let body = res.json();
return body.data || { } as Hero[];
}
private handleError (error: Response | any) {
// In a real world app, we might use a remote logging infrastructure
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
}
interface Hero {
}
Calling the getEvents method:
import { Component, OnInit } from '#angular/core';
import { EventListService } from '../services/event-list.service';
#Component({
selector: "event-list",
templateUrl: "./event-list/event-list.component.html",
styleUrls: ["./event-list/event-list.component.css"],
providers: [ EventListService ]
})
export class EventListComponent implements OnInit{
showImage: boolean = true;
searchString: string = "";
eventList: any[] = [];
constructor(private eventListService: EventListService) {
eventListService.getEvents();
}
ngOnInit() {
console.error("INIT");
}
toggleImage():void {
this.showImage = !this.showImage;
}
ratingClicked(data) {
console.error(data);
}
}
Your error could be here:
getEvents (): Observable<Hero[]> {
return this.http.get(this.heroesUrl)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response): Hero[] {
...
}
You see the missmatch. getEvents is returning an Observable of Hero Array, but your extractData is returning a Hero Array.
Just change your extractData to:
private extractData(res: Response) {
let body = res.json();
return body.data || { }
}
and I would suggest you move the call of getEvents to ngOnInit instead of the constructor, as per reference here, so do this instead:
ngOnInit() {
this.eventListService.getEvents()
.subscribe(d => {
this.eventList = d})
}
and eventList should be:
eventList: Hero[] = [];
Just subscribe to the service call, that is why it's not doing the request.
Change this:
export class EventListComponent implements OnInit{
showImage: boolean = true;
searchString: string = "";
eventList: any[] = [];
constructor(private eventListService: EventListService) {
eventListService.getEvents();
}
ngOnInit() {
console.error("INIT");
}
toggleImage():void {
this.showImage = !this.showImage;
}
ratingClicked(data) {
console.error(data);
}
}
For this:
export class EventListComponent implements OnInit{
showImage: boolean = true;
searchString: string = "";
eventList: any[] = [];
constructor(private eventListService: EventListService) {
eventListService.getEvents().subscribe((response:Hero[]) => {
console.log(response);
});
}
ngOnInit() {
console.error("INIT");
}
toggleImage():void {
this.showImage = !this.showImage;
}
ratingClicked(data) {
console.error(data);
}
}

Where to put service providers in angular 2 hierarchy so that components can talk to each other using the same instance of service?

Related question:
Observable do not receive the next value in angular2
No provider for service error in angular2, why do I need to inject it in it's parent component?
Using observable talk to other component in angular2, not receiving coming value
I have a PagesService that has a setCurrentPlaylists function, this function will be triggered from other component, it will receive an value of Playlists type, and will console log this value, using the next function pass to other component( I intent to).
My entire code for pages service is:
import { Injectable } from '#angular/core';
import { ApiService } from '../../apiService/api.service';
import { Platform } from '../../platforms/shared/platform.model';
import { Page } from './page.model';
import { Playlists } from '../shared/playlists.model';
import { Subject, BehaviorSubject } from 'rxjs/Rx';
#Injectable()
export class PagesService {
private currentPlaylists: Subject<Playlists> = new BehaviorSubject<Playlists>(new Playlists());
constructor(private service: ApiService) {
this.currentPlaylists.subscribe((v) => console.log(v, 'subscriber from pages service is printing out the incoming value'));
}
getPages(platform: Platform) {
return this.service.getPages(platform.value);
}
setCurrentPage(page: Page) {
this.service.setCurrentPage(page.pageId);
}
getCurrentPage():string {
return this.service.getCurrentPage();
}
getCurrentPlaylists() {
return this.currentPlaylists;
}
setCurrentPlaylists(playlists: Playlists) {
console.log("Pages Service receive an value of playlists:", playlists);
this.currentPlaylists.next(playlists);
}
}
My code for page component is:
import { Component, OnInit, Input, Output, OnChanges, EventEmitter, Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { Platform } from '../platforms/shared/platform.model';
import { Page } from './shared/page.model';
import { Playlists } from './shared/playlists.model';
import { PagesService } from './shared/pages.service';
import { PlaylistService } from '../playlist/shared/playlist.service';
import { Subject,BehaviorSubject } from 'rxjs/Rx';
#Component({
selector: 'pages',
styleUrls: ['app/pages/pages.css'],
templateUrl: 'app/pages/pages.html',
providers: [PagesService, PlaylistService]
})
export class PagesComponent {
#Input() platform: Platform;
#Output() onPlaylistsChange: EventEmitter<Playlists>;
currentPageName: string;
currentPage: Page;
pages: Array<Page>;
playlists: Playlists;
constructor(private pageServer: PagesService, private playlistService: PlaylistService) {
this.pages = [];
this.currentPage = new Page();
this.pageServer.setCurrentPage(this.currentPage);
this.playlists = new Playlists();
this.onPlaylistsChange = new EventEmitter<Playlists>();
}
ngOnInit() {
this.pageServer.getCurrentPlaylists().subscribe((playlists) => {
console.log('subscriber in pages component is printing out the incoming value', playlists);
this.playlists = playlists;
}, error => {
console.log(error);
});
}
getPages(platform: Platform): void {
this.pageServer.getPages(platform)
.subscribe(
res => {
if (res.pages.length > 0) {
this.pages = [];
for (let page of res.pages) {
if (page.pageName !== "Shows" && page.pageName !== "All Shows" && page.pageName !== "Moives" && page.pageName !== "All Movies") {
this.pages.push(page);
}
}
this.currentPage = this.pages[0];
this.pageServer.setCurrentPage(this.currentPage);
this.currentPageName = this.pages[0].pageName;
this.getPlaylist(this.currentPage, this.platform);
} else {
this.pages = [];
this.currentPage = new Page();
this.pageServer.setCurrentPage(this.currentPage);
this.playlists = new Playlists();
this.onPlaylistsChange.emit(this.playlists);
}
},
error => console.log(error)
);
}
getPlaylist(page: Page, platform: Platform): void {
this.currentPage = page;
this.pageServer.setCurrentPage(this.currentPage);
this.playlistService.getPlaylist(page, platform)
.subscribe(
res => {
if (res.hasOwnProperty('pages') && res.pages.length > 0) {
if (res.pages[0].hasOwnProperty('bodyPlaylists') && res.pages[0].hasOwnProperty('headerPlaylists')) {
this.playlists.bodyPlaylists = res.pages[0].bodyPlaylists || [];
this.playlists.headerPlaylists = res.pages[0].headerPlaylists || [];
} else {
this.playlists.bodyPlaylists = [];
this.playlists.headerPlaylists = [];
this.playlists.wholePlaylists = res.pages[0].playlists || [];
}
this.onPlaylistsChange.emit(this.playlists);
} else {
this.playlists = new Playlists();
this.onPlaylistsChange.emit(this.playlists);
}
},
error => console.error(error)
);
}
ngOnChanges() {
// Get all Pages when the platform is set actual value;
if (this.platform.hasOwnProperty('value')) {
this.getPages(this.platform);
}
}
}
When I trigger the setCurrentPlaylists function, the playlists didn't passed to pages component. I need to use that passed value to update pages component's playlists.
This is the console output after I trigger the setCurrentPlaylsts function. No message from pages components.
Any suggestions are appreciated!
I call setCurrentPlaylists function from this component
/// <reference path="../../../typings/moment/moment.d.ts" />
import moment from 'moment';
import { Component, ViewChild, ElementRef, Input, Output, EventEmitter } from '#angular/core';
import { CORE_DIRECTIVES } from '#angular/common';
import { Http, Response } from '#angular/http';
import { MODAL_DIRECTVES, BS_VIEW_PROVIDERS } from 'ng2-bootstrap/ng2-bootstrap';
import {
FORM_DIRECTIVES,
REACTIVE_FORM_DIRECTIVES,
FormBuilder,
FormGroup,
FormControl,
Validators
} from '#angular/forms';
import { PagesService } from '../../pages/shared/pages.service';
import { ApiService } from '../../apiService/api.service';
#Component({
selector: 'assign-playlist-modal',
providers: [PagesService],
exportAs: 'assignModal',
directives: [MODAL_DIRECTVES, CORE_DIRECTIVES, FORM_DIRECTIVES, REACTIVE_FORM_DIRECTIVES ],
viewProviders: [BS_VIEW_PROVIDERS],
styleUrls: ['app/channel/shared/assignPlaylist.css'],
templateUrl: 'app/channel/modals/assignPlaylistModal.html'
})
export class AssignPlaylistModalComponent {
#ViewChild('assignPlaylistModal') modal: any;
private addPlaylistForm: FormGroup;
private playlistType: string;
private currentPage: string;
private editDate: string;
constructor(private apiService: ApiService, private pagesService: PagesService, fb: FormBuilder) {
this.currentPage = '';
this.editDate = this.apiService.getDate();
this.addPlaylistForm = fb.group({
'longPlaylistName': ['', Validators.required],
'shortPlaylistName': ['', Validators.required],
'startOn': ['', Validators.compose([
Validators.required, this.validTimeFormat
])],
'expireOn': ['', Validators.compose([
Validators.required, this.validTimeFormat
])],
'isExpire': ['']
});
this.addPlaylistForm.controls['startOn'].valueChanges.subscribe((value: string) => {
if (moment(value, 'YYYY-MM-DDThh:mm').isValid()) {
if (this.playlistType == 'dynamic') {
this.apiService.setGlobalStartTime(moment(value).format("YYYYMMDDHHmm"));
}
}
});
this.addPlaylistForm.controls['expireOn'].valueChanges.subscribe((value: string) => {
if (moment(value, 'YYYY-MM-DDThh:mm').isValid()) {
if (this.playlistType == 'dynamic') {
this.apiService.setGlobalEndTime(moment(value).format("YYYYMMDDHHmm"));
}
}
});
}
showModal(type: string) {
this.playlistType = type;
this.currentPage = this.apiService.getCurrentPage();
this.modal.show();
}
validTimeFormat(control: FormControl): { [s: string]: boolean} {
if (!moment(control.value, 'YYYY-MM-DDThh:mm').isValid()) {
return { invalidTime: true};
}
}
setCloseStyle() {
let styles = {
'color': 'white',
'opacity': 1
}
return styles;
}
createNewPlaylist(stDate: string, etDate: string, playlistTitle: string, shortTitle: string, callback?: any):any {
this.apiService.createNewPlaylist(stDate, etDate, playlistTitle, shortTitle)
.subscribe(
data => {
let playlistId = data[0].id;
this.apiService.addPlaylistToPage(playlistId, stDate, etDate, this.apiService.getGlobalRegion(), callback)
.subscribe(
data => {
if (this.apiService.g_platform == 'DESKTOP') {
this.apiService.getPlaylist(this.apiService.getCurrentPage(), 'true' )
.subscribe(
res => {
if (res.hasOwnProperty('pages') && res.pages.length > 0) {
if (res.pages[0].hasOwnProperty('bodyPlaylists') && res.pages[0].hasOwnProperty('headerPlaylists')) {
this.apiService.getCurrentPlaylists().bodyPlaylists = res.pages[0].bodyPlaylists || [];
this.apiService.getCurrentPlaylists().headerPlaylists = res.pages[0].headerPlaylists || [];
console.log('assign playlist component is calling the pages service setCurrentPlaylists function.');
this.pagesService.setCurrentPlaylists(this.apiService.getCurrentPlaylists());
} else {
this.apiService.getCurrentPlaylists().bodyPlaylists = [];
this.apiService.getCurrentPlaylists().headerPlaylists = [];
this.apiService.getCurrentPlaylists().wholePlaylists = res.pages[0].playlists || [];
console.log('assign playlist component is calling the pages service setCurrentPlaylists function.');
this.pagesService.setCurrentPlaylists(this.apiService.getCurrentPlaylists());
}
}
}
);
} else {
this.apiService.getPlaylist(this.apiService.getCurrentPage(), 'false' )
.subscribe(
res => {
if (res.hasOwnProperty('pages') && res.pages.length > 0) {
this.apiService.getCurrentPlaylists().bodyPlaylists = [];
this.apiService.getCurrentPlaylists().headerPlaylists = [];
this.apiService.getCurrentPlaylists().wholePlaylists = res.pages[0].playlists || [];
console.log('assign playlist component is calling the pages service setCurrentPlaylists function.');
this.pagesService.setCurrentPlaylists(this.apiService.getCurrentPlaylists());
}
}
);
}
}
);
},
error => console.log(error)
);
}
onSubmit(form: FormGroup) {
// get start time, the format from input will be like 2016-06-07T00:05
let startTime = moment(form.value.startOn).format("YYYYMMDDHHmm");
let expireTime = moment(form.value.expireOn).format("YYYYMMDDHHmm");
let playlistTitle = form.value.longPlaylistName;
let shortTitle = form.value.shortPlaylistName;
if (this.playlistType == 'smart' || this.playlistType == 'new') {
this.createNewPlaylist(startTime, expireTime, playlistTitle, shortTitle);
}
}
}
This is my component tree:
I am assuming your components tree is as follow:
AssignPlaylistModalComponent (Parent or higher level than PagesComponent in the tree)
PagesComponent (lowest level child as it does not import any directive)
Issue
You should only put your service in the top level (parent) components provider. Though all components still need to do the import and constructor.
Putting the service in a component's provider will create a new copy of the service and share along the component tree downward, not upward.
In the code in question, PagesComponent, as the lowest level child in the tree, with its own provider line, is actually initiating its own copy of PagesService, PlaylistService. So each instance of PagesComponent is basically listening to itself only. It won't receive any messages from others.
Fix
#Component({
selector: 'pages',
styleUrls: ['app/pages/pages.css'],
templateUrl: 'app/pages/pages.html',
providers: [PagesService, PlaylistService] // <--- Delete this line
})
export class PagesComponent {
#Input() platform: Platform;
#Output() onPlaylistsChange: EventEmitter<Playlists>;
Where to put providers
Assume following component tree:
Component A1 (root component)
Component B1
Component C1
Component C2
Component B2
Component C3
Component C4
The easiest way is to put it in A1 providers, all components will be sharing the same service instance, and able to message each other.
If you put it in B1 providers, then only B1, C1 and C2 can talk to each other.
Base on lastest update, the root component of the project is AppComponent.ts. providers should be added in it.
From the code you provided, I cannot see when this method
setCurrentPlaylists(playlists: Playlists) {
console.log(playlists, 'i am here');
this.currentPlaylists.next(playlists);
}
is called. Therefore, your list is empty.
Doing this
this.pageServer.getCurrentPlaylists().subscribe((playlists) => {
console.log(playlists, 'new playlists coming');
this.playlists = playlists;
}, error => {
console.log(error);
});
only creates a subscription to the observable. You need to publish data from somewhere.
In addition, it'd better to move this code
this.pageServer.getCurrentPlaylists().subscribe((playlists) => {
console.log(playlists, 'new playlists coming');
this.playlists = playlists;
}, error => {
console.log(error);
});
to ngOnInit()

Categories

Resources