check boolean value again and again - javascript

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);
}
});

Related

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);

Theme switcher on localstorage observable service

I implemented a dynamic theme switcher (with tutorial) in my angular app. It work's but when I reload website, the choice is not remembered.
I read about localStorage and i will use it but still doesn't work because I don't know how "where" I should get data from this localStorage, that the choice of the theme will be remembered when I reload the page.
I have this code:
theme.service.ts new version
import { Injectable } from '#angular/core';
import { Subject } from 'rxjs/Subject';
#Injectable()
export class ThemeService {
private _themeDark: Subject<boolean> = new Subject<boolean>();
isDarkFunction() {
let value = localStorage.getItem('isDark');
this._themeDark.next(value);
return this._themeDark.asObservable();
}
isThemeDark = this.isDarkFunction();
setDarkTheme(isThemeDark: boolean) {
this._themeDark.next(isThemeDark);
localStorage.setItem('isDark', JSON.stringify(isThemeDark));
}
}
navbar.component.html
<div class="container-fluid switcher-container">
<mat-slide-toggle [checked]="isThemeDark | async" (change)="toggleDarkTheme($event.checked)">Dark theme</mat-slide-toggle>
</div>
navbar.component.ts
import { Component, OnInit } from '#angular/core';
import { ThemeService } from '../services/theme.service';
import { Observable } from 'rxjs/Observable';
#Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.scss']
})
export class NavbarComponent implements OnInit {
isThemeDark: Observable<boolean>;
constructor(
private themeService: ThemeService) { }
ngOnInit() {
this.isThemeDark = this.themeService.isThemeDark;
}
toggleDarkTheme(checked: boolean) {
this.themeService.setDarkTheme(checked);
}
}
app.component.ts
import { Component, OnInit } from '#angular/core';
import { Observable } from "rxjs/Observable";
import { ThemeService } from "./services/theme.service";
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
providers: [ThemeService]
})
export class AppComponent implements OnInit {
isThemeDark: Observable<boolean>;
constructor(
public themeService: ThemeService) {
}
ngOnInit() {
this.isThemeDark = this.themeService.isThemeDark;
}
}
Please help,
Regards
You might write something like the following in theme.service.ts.
I don't know if it will run flawlessly as is but the idea is to read from localstorage in isThemeDark().
isThemeDark() {
let value = localStorage.getItem('isDark');
this._themeDark.next(value);
return this._themeDark.asObservable();
}
I think it's because you when you do localStorage.getItem('isDark') the result is a string, not a boolean. Maybe try:
let value = JSON.parse(localStorage.getItem('isDark')) === true;
Also check manually if the localstorage is kept after a refresh. Some browsers have a setting to clear everything on refresh.

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

angular 5 behaviorsubject not working with http [duplicate]

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 ]
})

(Angular2) JSON data (http.get()) is undefined, and data is not updated in the component

My http-data.service accepts json for output in the component template. Initially, the console shows that the first few calls are given undefined, and the following calls are already taking json, but also if you check the component, then the component shows that the method that outputs the data to the component is called only once and since the data has not yet arrived it writes undefined , But not updated after the arrival of json. Help please understand why? Thank you
My http-data.service:
import {Injectable} from '#angular/core';
import {Http} from '#angular/http';
import {Response} from '#angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
#Injectable()
export class HttpService{
constructor(private http: Http) {}
getDataOrganizations(): Observable<any[]>{
return this.http.get('http://localhost:3010/data')
.map((resp:Response)=>{
let dataOrganizations = resp.json().organization;
return dataOrganizations;
});
}
getDataModules(): Observable<any[]> {
return this.http.get('http://localhost:3010/data')
.map((resp: Response)=> {
let dataModules = resp.json().modules;
return dataModules;
});
}
getDataPresets(): Observable<any[]> {
return this.http.get('http://localhost:3010/data')
.map((resp: Response)=> {
let dataPresets = resp.json().presets;
return dataPresets;
});
}
getDataModuleItems(): Observable<any[]> {
return this.http.get('http://localhost:3010/data')
.map((resp: Response)=> {
let dataModuleItems = resp.json().module_items;
return dataModuleItems;
});
}
}
My data-all.service
import { Injectable, EventEmitter } from '#angular/core';
import {Response} from '#angular/http';
import { ModuleModel } from './model-module';
import { ModuleItemsModel } from './model-module-items';
import data from '../data/data-all';
import { PriceService } from './price.service';
import { HttpService } from './http-data.service';
#Injectable()
export class ModuleDataService {
constructor(private priceService: PriceService, private httpService: HttpService){
this.dataMinMaxSum = {minSum: 0, maxSum: 0}
}
private currentPopupView: EventEmitter<any> = new EventEmitter<any>();
private dataModules: ModuleModel[] = this.getDataModules();
private dataMinMaxSum: {};
private dataCalculateVariationOrg: any[];
private dataChangeExecutor: any[];
subscribe(generatorOrNext?: any, error?: any, complete?: any) {
this.currentPopupView.subscribe(generatorOrNext, error, complete);
}
calculte(){
return this.priceService.getDataPrice();
}
getDataModules(){
this.httpService.getDataModules().subscribe(((modules)=>{this.dataModules = modules; console.log(this.dataModules);}));
console.log('dataModules');
console.log(this.dataModules);
return this.dataModules;
}
---------------------------------------------------------------------------
}
My left-block.component
import { Component, OnInit} from '#angular/core';
import { ModuleDataService } from '../../service/data-all.service';
import { ModuleModel } from '../../service/model-module';
#Component({
moduleId: module.id,
selector: 'modules-left-block',
templateUrl: './modules-left-block.html',
styleUrls: ['modules-left-block.css']
})
export class ModuleLeft implements OnInit{
modules: ModuleModel[];
constructor(private modulesAll: ModuleDataService){}
ngOnInit(){
this.modules = this.modulesAll.getDataModules();
console.log("view");
console.log(this.modulesAll.getDataModules());
}
onToggle(module: any){
this.modulesAll.toggleModules(module);
}
}
My left-block.component.html
<div class="modules-all">
<div class="modules-all-title">Все модули</div>
<div class="module-item" *ngFor="let module of modules" [ngClass]="{ 'active': module.completed }" (click)="onToggle(module)">{{module?.title}}</div>
</div>
In the component this.modulesAll.getDataModules () method is why it is executed only once without updating (write in console => undefined), if there are any thoughts, write, thanks.
This behaviour is due to the .subscribe() method does not wait for the data to arrive and I'm guessing you already know this. The problem you're facing is because, you have .subscribe to the getDataModules() service in the wron place. You shouldn't subscribe to a service in another service (at leat in this case). Move the subscribe method to the left-block.component and it should work.
getDataModules() {
this.httpService.getDataModules().subscribe(((modules) => {
this.dataModules = modules;
console.log(this.dataModules);
}));
console.log('dataModules');
console.log(this.dataModules);
return this.dataModules;
}
It should look somethig like this:
#Component({
moduleId: module.id,
selector: 'modules-left-block',
templateUrl: './modules-left-block.html',
styleUrls: ['modules-left-block.css']
})
export class ModuleLeft implements OnInit {
modules: ModuleModel[] = new ModuleModel();
constructor(private modulesAll: ModuleDataService, private httpService: HttpService) {}
ngOnInit() {
this.getDataModles();
//this.modules = this.modulesAll.getDataModules();
console.log("view");
//console.log(this.modulesAll.getDataModules());
}
onToggle(module: any) {
this.modulesAll.toggleModules(module);
}
getDataModules(): void {
this.httpService.getDataModules().subscribe(((modules) => {
this.modules = modules;
console.log(this.dataModules);
}));
}
}

Categories

Resources