angular 5 behaviorsubject not working with http [duplicate] - javascript

This question already has answers here:
Angular 2 Shared Data Service is not working
(3 answers)
Closed 4 years ago.
I am trying to get user type from the server and based on the role of the user display data. The http servise is running file and returning the desired data. I have two components. Login and Home components. After login a boolean variable is set to decide if the user is Admin or User. The login function is showing isAdmin variable true. But home component is showing it as false. I am using behaviorsubject and observable to sync the data.
Service
import { Injectable } from '#angular/core';
import {Http, Response} from "#angular/http";
import {Observable} from "rxjs/Observable";
import "rxjs/Rx";
import {IPosts} from "./posts";
import {IUser} from "./user";
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
#Injectable()
export class ExamService {
public isAdmin = new BehaviorSubject<boolean>(false);
cast = this.isAdmin.asObservable();
private _postsURL = "http://localhost:3292/examservice.svc/ExamQs";
private _userURL = "http://localhost:3292/examservice.svc/GetUser";
constructor(private http: Http) {
}
getPosts(): Observable<IPosts[]> {
return this.http
.get(this._postsURL)
.map((response: Response) => {
return <IPosts[]>response.json();
})
.catch(this.handleError);
}
getUser(user:string,pass:string): Observable<IUser[]> {
return this.http
.get(this._userURL+"/"+user+"/"+pass)
.map((response: Response) => {
return <IUser[]>response.json();
})
.catch(this.handleError);
}
checkAdmin(data){
this.isAdmin.next(data);
}
private handleError(error: Response) {
return Observable.throw(error.statusText);
}
}
Login Component
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { ExamService } from "../exam.service";
import {IPosts} from "../posts";
import {IUser} from "../user";
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css'],
providers: [ ExamService ]
})
export class LoginComponent implements OnInit {
_postsArray: IPosts[];
_userArray: IUser[];
ifuser: boolean = false;
Name: string;
Pass: string;
validated: boolean = true;
constructor(private apiSerivce: ExamService,private router:Router) { }
getPosts(): void {
this.apiSerivce.getUser(this.Name,this.Pass)
.subscribe(
resultArray => {
this._userArray = resultArray;
if(this._userArray[0].Role == "Admin")
{
this.ifuser = true;
this.apiSerivce.checkAdmin(this.ifuser);
}
else
{
this.apiSerivce.checkAdmin(this.ifuser);
this.router.navigate(['']);
}
},
error => console.log("Error :: " + error)
)
console.log(this.ifuser);
this.router.navigate(['']);
}
ngOnInit(): void {
this.apiSerivce.cast.subscribe(data =>
{
this.validated = data;
console.log("Login " + this.validated);
});
}
}
Home Component
import { Component, OnInit } from '#angular/core';
import { ExamService } from "../exam.service";
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css'],
providers: [ ExamService ]
})
export class HomeComponent implements OnInit {
validated: boolean;
constructor(private apiSerivce: ExamService) { }
ngOnInit() {
this.apiSerivce.cast.subscribe(data =>
{
this.validated = data;
console.log("Home " + this.validated);
});
}
}

I have found the solution to this problem. Do not add service as provider in the child components instead add provider in app.component.ts file which is a parent component. so instead of
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css'],
providers: [ ExamService ]
})
it should be like this in child components
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css'],
})
and in app.component.ts file it should be like this
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [ ExamService ]
})

Related

displaying items from DB using Angular 12

the Item file
component file
the data service file
when I test my code with console log statements it says data from service is undefined
import { Component, OnInit } from '#angular/core';
import { Item } from '../item';
import { DataService } from '../data.service';
#Component({
selector: 'app-shopping-item',
templateUrl: './shopping-item.component.html',
styleUrls: ['./shopping-item.component.css'],
providers: [DataService]
})
export class ShoppingItemComponent implements OnInit {
shoppingItemList: Item[] = [];
constructor(private dataservice: DataService){}
getItems(){
this.dataservice.getShoppingItems()
.subscribe(items =>{
this.shoppingItemList.push(items),
console.log('data from dataservice '+ this.shoppingItemList[0].itemName);
})
}
addItem(form: any){
console.log(form)
}
ngOnInit(): void {
this.getItems();
}
}
If you are receiving an array from the API call, then you need to either assign it directly to the property (1) or destructure the array into the property (2)
Currently I guess you are pushing an array inside an array, which might lead to undefined error!
import { Component, OnInit } from '#angular/core';
import { Item } from '../item';
import { DataService } from '../data.service';
#Component({
selector: 'app-shopping-item',
templateUrl: './shopping-item.component.html',
styleUrls: ['./shopping-item.component.css'],
providers: [DataService]
})
export class ShoppingItemComponent implements OnInit {
shoppingItemList: Item[] = [];
constructor(private dataservice: DataService){}
getItems(){
this.dataservice.getShoppingItems()
.subscribe(items =>{
this.shoppingItemList = items; // solution 1
// this.shoppingItemList.push(...items); // solution 2
console.log('data from dataservice '+ this.shoppingItemList[0].itemName);
})
}
addItem(form: any){
console.log(form)
}
ngOnInit(): void {
this.getItems();
}
}

check boolean value again and again

I am trying to build infinite scroll for my cards.
I am using a variable reload in data.service to check for need to load more data which is getting set to true when page end is getting reached.
The variable setting to true is done by app.component
The content population is done in post.component
And ```reload`` is present in data.service which is using http service to fetch for content from php server.
Curently I am using observable and trying to access reload status repeatedly but it is getting subscribed only once on Init.
app.component.ts
import { Component,HostListener } from '#angular/core';
import * as M from 'materialize-css';
import {DataService} from './current/posts/post-card/data.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent
{
title = 'cosmos';
constructor(private scrollSet: DataService){}
#HostListener('scroll', ['$event'])
onScroll(event:any)
{
if (event.target.offsetHeight + event.target.scrollTop >= event.target.scrollHeight-100)
{
console.log("noww");
this.scrollSet.setValue(true);
}
}
}
post.component.ts
import { Component, OnInit} from '#angular/core';
import {DataService} from './data.service';
import { DomSanitizer } from '#angular/platform-browser';
import {Title} from "#angular/platform-browser";
#Component({
selector: 'app-post-card',
templateUrl: './post-card.component.html',
styleUrls: ['./post-card.component.css']
})
export class PostCardComponent implements OnInit {
constructor(private data: DataService,public sanitizer: DomSanitizer,private titleService:Title)
{
this.titleService.setTitle("Current Feed | Cosmos");
}
received = 'none';
posts: any = [];
ngOnInit()
{
this.data.getPostData().subscribe(data =>
{
this.posts.push(data);
this.received='success';
},
error =>
{
this.received='error';
});
this.data.getValue().subscribe((value) => {
this.data.getPostData().subscribe(data =>
{
this.posts.push(data);
this.received='success';
},
error =>
{
this.received='error';
});
});
}
}
data.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import {BehaviorSubject, Observable} from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class DataService {
private reload: BehaviorSubject<boolean>;
constructor(private http: HttpClient)
{
this.reload = new BehaviorSubject<boolean>(false);
}
fetchGap=5; // use this to set number of results wanted per fetch
fetchEnd:number= 0;
setValue(newValue): void {
this.reload.next(newValue);
}
getValue(): Observable<boolean> {
return this.reload.asObservable();
}
getPostData(){
this.fetchEnd+=this.fetchGap;
return this.http.get('http://localhost:1234/Server/getPosts.php?fetchEnd='+this.fetchEnd+'&fetchGap='+this.fetchGap);
}
}
the problem is that you haven't set the value of reload to false after your treatment.
try to check inside post.component.ts. here is a portion of that code, the block which suscribe to reload.
post.component.ts reload block
this.data.getValue().subscribe((value) => {
if(value){
this.data.getPostData().subscribe(data =>
{
this.posts.push(data);
this.received='success';
},
error =>
{
this.received='error';
});
this.data.setValue(false);
}
});

ANGULAR. Send array data get it of Itunes API; from component-search to component-main, via service

In angular 7. I need to send an Array information get it from Itunes Api, which is included in a component called "search", to another component called "catalog". I've understand that in this case I've to use a service which allows to share the info between them. Here's some code. What's wrong?
I've tried with viewchild, input, output, but there's no result; because both components aren't "relatives".
"search"
"search"
import { Component, OnInit, Output, EventEmitter } from '#angular/core';
import { RequestService } from '../../services/request/request.service';
import {DataShareService} from '../../services/dataShare/data-share.service';
import { Music } from '../../models/music';
#Component({
selector: 'search',
styleUrls: ['./ion-searchbar.component.sass'],
templateUrl: './ion-searchbar.component.html',
providers: [RequestService, DataShareService],
})
export class IonSearchBarComponent implements OnInit {
public searchResults: Music[];
public searchValue: string;
constructor(public _requestService: RequestService, private _dataShareService: DataShareService) {}
ngOnInit() {
this._dataShareService.$sendDataObservable.subscribe(
data => {
this.searchResults = data
})
}
sendData(searchResults: Music[]){
console.log("executat");
this._dataShareService.sendData(searchResults);
}
search(){
this._requestService.getMusic(this.searchValue).subscribe(
result => {
this.searchResults = result.results;
console.log(result.results);
this.sendData(this.searchResults);
},
error =>{
console.log(<any>error);
}
);
}
}
"service"
import { Injectable } from '#angular/core';
import { Music } from '../../models/music';
import { Subject } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class DataShareService {
private _sendDataSubject = new Subject<Music[]>();
$sendDataObservable = this._sendDataSubject.asObservable();
constructor() { }
sendData(data: Music[]){
this._sendDataSubject.next(data);
console.log(data);
}
}
"catalog"
import { Component, OnInit, Input } from '#angular/core';
import {RequestService} from '../../services/request/request.service';
import {DataShareService} from '../../services/dataShare/data-share.service';
import { Music } from '../../models/music';
#Component({
selector: 'catalog',
templateUrl: './catalog.component.html',
styleUrls: ['./catalog.component.sass'],
providers: [RequestService, DataShareService]
})
export class CatalogComponent implements OnInit {
public title: any;
public InfoLlegada: any;
constructor(private _dataShareService: DataShareService) {}
ngOnInit() {
console.log(this.InfoLlegada)
this._dataShareService.$sendDataObservable.subscribe(
data => {
this.InfoLlegada = data
console.log(data);
});
}
}
Not sure if this is the actual cause, but there an issue with your this binding in getMusic subscription in search component. Try this.sendData.call(this, result.results);

Call modal from one sibling component to other angular

I have this Angular6 component arquitecture in my app
Main component
<app-navbar></app-navbar>
<app-dashboard></app-dashboard>
Dashboard component
<app-meseros>
</app-meseros>
<app-ultimospedidos></app-ultimospedidos>
<app-modal></app-modal>
I want to call modal from navbar.component, my modal is on dashboard on component modal.component
This is what i have tried
<!--navbar.component.html -->
<a class="nav-link btn btn-primary" (click)="openModal()">Crear pedido</a>
<!--navbar.component.ts -->
import { Component, OnInit } from '#angular/core';
import { BootstrapService } from '../../services/bootstrap.service';
#Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {
constructor(public bootstrapService: BootstrapService) {}
ngOnInit() {}
openModal() {
this.bootstrapService.toggle();
}
}
I created a service so i can communicate between my navbar.component and modal.component, this is my service
import { Injectable } from '#angular/core';
#Injectable({
providedIn: 'root'
})
export class BootstrapService {
isOpen: any = false;
constructor() {}
toggle() {
console.log(!this.isOpen);
return (this.isOpen = !this.isOpen);
}
}
Then in modal.component.ts i want to subscribe to these changes so i can launch modal on boolean value change.
import { Component, OnInit } from '#angular/core';
import { BootstrapService } from '../../services/bootstrap.service';
import { NgbModal, ModalDismissReasons } from '#ng-bootstrap/ng-bootstrap';
#Component({
selector: 'app-modal',
templateUrl: './modal.component.html',
styleUrls: ['./modal.component.css']
})
export class ModalComponent implements OnInit {
isOpen;
closeResult: string;
modalname: string;
constructor(
public modalService: NgbModal,
public bootstrapService: BootstrapService
) {}
open(content) {
// console.log(this.bootstrapService.popup);
this.modalService
.open(content, { ariaLabelledBy: 'modal-basic-title' })
.result.then(
result => {
this.closeResult = `Closed with: ${result}`;
},
reason => {
this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
}
);
}
private getDismissReason(reason: any): string {
if (reason === ModalDismissReasons.ESC) {
return 'by pressing ESC';
} else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
return 'by clicking on a backdrop';
} else {
return `with: ${reason}`;
}
}
ngOnInit() {
this.bootstrapService.toggle().subscribe(isOpen => {
this.isOpen = isOpen;
console.log(isOpen);
});
}
}
Im not even able to subscribe to the change from bootstrapService, i get following error,
RROR in src/app/components/modal/modal.component.ts(41,36): error TS2339: Property 'subscribe' does not exist on type 'boolean'.
if i try to subscribe to value on service like this
this.bootstrapService.isOpen.subscribe(isOpen => {
this.isOpen = isOpen;
console.log(isOpen);
});
i get error on console from browser which says
DashboardComponent.html:1 ERROR TypeError: this.bootstrapService.isOpen.subscribe is not a function
i hope someone can shade some light on this approach, and if this is the best approach to take on this kind of implementations, thanks in advance!
Solved it, i was calling wrong EventEmitter from wrong library, this is updated working code
first i call service from component where i want to call my modal
import { Component, OnInit } from '#angular/core';
import { BootstrapService } from '../../services/bootstrap.service';
#Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {
constructor(public bootstrapService: BootstrapService) {}
ngOnInit() {}
openModal() {
this.bootstrapService.toggle();
}
}
Then i emit my changes so i can subscribe from modal component
import { Injectable, Output, EventEmitter } from '#angular/core';
#Injectable({
providedIn: 'root'
})
export class BootstrapService {
isOpen: any = 'isOpen';
#Output() change: any = new EventEmitter();
constructor() {}
toggle() {
this.change.emit(this.isOpen);
console.log(this.isOpen);
}
}
i reference my template with `#ViewChild('crearpedido') modalInstance;`
and finally subscribe to changes, call modal on subscribe changes.
import { Component, OnInit, ViewChild } from '#angular/core';
import { BootstrapService } from '../../services/bootstrap.service';
import { NgbModal } from '#ng-bootstrap/ng-bootstrap';
#Component({
selector: 'app-modal',
templateUrl: './modal.component.html',
styleUrls: ['./modal.component.css']
})
export class ModalComponent implements OnInit {
isOpen;
closeResult: string;
#ViewChild('crearpedido') modalInstance;
constructor(
public modalService: NgbModal,
public bootstrapService: BootstrapService
) {}
ngOnInit() {
this.bootstrapService.change.subscribe(isOpen => {
this.isOpen = isOpen;
console.log(this.isOpen);
this.modalService.open(this.modalInstance);
});
}
}
Here is working repo!!
https://github.com/soyisraelortiz/componentscommunication

Why can't I fetch a file in angular 2?

Basically I am trying to fetch a csv file to parse it later using d3.
I have created a special component to fetch the data, and pass it to another component to parse it.
The fetch-data component is as follows:
import {Component, Injectable} from '#angular/core';
import {Http, Response, Headers, RequestOptions, HttpModule} from "#angular/http";
import {Observable} from 'rxjs/Rx';
#Component({
selector: 'app-fetch-data',
templateUrl: './fetch-data.component.html',
styleUrls: ['./fetch-data.component.css'],
providers: [HttpModule]
})
#Injectable()
export class FetchDataComponent {
constructor(private http: Http) {
}
getCsv(): Observable<any> {
return this.http.get('app/districts_data/data.csv').map((res: Response) => res);
}
}
Here is the other component where the d3 code should go:
import {Component, OnInit, ElementRef} from '#angular/core';
import * as D3 from 'd3';
import {FetchDataComponent} from '../fetch-data/fetch-data.component';
#Component({
selector: 'app-dubai-dual-line-chart',
templateUrl: './dubai-dual-line-chart.component.html',
styleUrls: ['./dubai-dual-line-chart.component.css'],
providers: [FetchDataComponent]
})
export class parseData implements OnInit {
public csv;
constructor(private __fetchDataComponent: FetchDataComponent) {}
ngOnInit() {
this.getCsv();
}
private getCsv() {
this.__fetchDataComponent.getCsv().subscribe(
data => {
this.csv = data
},
err => console.error(err),
() => console.log('done loading csv')
)
}
}
But nothing seems to be fetched. Where did I go wrong?

Categories

Resources