Firebase Cloud Firestore can not load data - html

When I open web data is show but I change component and come back this component data not show.It show no item. I check log but not run to ngOnIt. ngOnIt run on web strat or web reload.
this is stock.service.ts
import { Injectable } from '#angular/core';
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from 'angularfire2/firestore';
import { Observable } from 'rxjs/Observable';
import { Stock } from './stock.model';
#Injectable()
export class StockService {
stocksCollection: AngularFirestoreCollection<Stock>;
stocks: Observable<Stock[]>;
constructor(public afs: AngularFirestore) {
this.stocks = this.afs.collection('stocks').valueChanges();
}
getStock(){
return this.stocks;
}
}
stock.component.ts
import { Component, OnInit, Input } from '#angular/core';
import { ActivatedRoute,Params } from '#angular/router';
import { StockService } from '../shared/stock.service';
import { Stock } from '../shared/stock.model';
import { Brands } from '../shared/brand';
import { Subscription } from 'rxjs/Subscription';
#Component({
selector: 'app-stock',
templateUrl: './stock.component.html',
styleUrls: ['./stock.component.css']
})
export class StockComponent implements OnInit {
stocks: Stock[];
brand: Brands;
sub: Subscription;
brand_name: string;
constructor(
private stockService: StockService,
private router: ActivatedRoute
) { }
ngOnInit() {
this.stockService.getStock().subscribe(stocks => {
console.log(stocks);
this.stocks = stocks;
});
this.sub = this.router.params.subscribe(params =>{
this.brand_name = params['brand'];
});
console.log('Brand : '+this.brand_name);
}
}
and stock.component.html
<div *ngIf="stocks != null || stocks?.length > 0 ; else noStocks" >
<ul *ngFor="let item of stocks" class="collection">
<li class="collection-item " >{{item.name}} | {{item.brand}} | {{item.price}}</li>
</ul>
</div>
<ng-template #noStocks>
<p>no item</p>
</ng-template>
I don't know where code is mistake. Thank you for answer.

Don't load inside the constructor of your service, move it inside your method
constructor(public afs: AngularFirestore) {
}
getStock(){
this.stocks = this.afs.collection('stocks').valueChanges();
return this.stocks;
}

Related

Problem with My Wish List Items Showing Source unknown

I am having a problem showing my wish list items on the page. I'm using Angular 10 and json. Wen I click to add to favorites it color the heart and add it to to my json folder under wishlistitem, but when I route to page to look at the items no products are there. I can tell it hits the the *ngFor because the pipe for the dollar amount for each item appears but no images. When inspecting the source it shows src=unknown.
I have two folders wishlist-list and wishlistitem. I have a service for wishlistitem that is where I think my problem resides. I have included my code.
import { Component, OnInit, Input } from '#angular/core';
import {ProductService} from 'src/app/services/product.service'
import { MessengerService } from 'src/app/services/messenger.service';
import { WishlistService } from 'src/app/services/wishlist.service';
import { WishlistItemService } from '#app/services/wishlist-item.service';
import { Wish} from 'src/app/models/wish';
import {Product} from 'src/app/models/product';
#Component({
selector: 'app-wishlist-list',
templateUrl: './wishlist-list.component.html',
styleUrls: ['./wishlist-list.component.scss']
})
export class WishlistListComponent implements OnInit {
productList: Product[]= [];
wishlistItem: Wish[]= [];
wishItem = []
constructor( private msg: MessengerService,
private productService: ProductService,
private wishlistService: WishlistService,
private _wishlistitemService: WishlistItemService ) { }
ngOnInit(): void {
this.loadWishlistList();
}
loadWishlistList(){
this._wishlistitemService.getWishlistitem().subscribe((items: Wish[]) => {
this.wishItem= items;
this.msg.sendMsg("Is the item being captured" + items)
})
}
}
//Here is my Wishlist-list HTML
<p>wishlist-list works!</p>
<div class="container">
<div class="row">
<div class="col-md-2" *ngFor="let product of wishItem">
<app-wishlistitem [wishitemItem]="product"></app-wishlistitem>
</div>
</div>
</div>
//Here is my wishlist item service
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { wishlistitemUrl } from 'src/app/config/api';
import { map } from 'rxjs/operators';
import { ProductItemComponent } from '#app/shopping-cart/product-list/product-
item/product-item.component';
import { Observable, of } from 'rxjs';
import { catchError} from 'rxjs/operators';
import {Product} from 'src/app/models/product';
import {Wish} from 'src/app/models/wish';
#Injectable({
providedIn: 'root'
})
export class WishlistItemService {
product:any
wishlistitemUrl = 'http://localhost:3000/wishlistitem';
constructor(private http: HttpClient) { }
getWishlistitem(): Observable<Wish[]>{
return this.http.get<Wish[]>(wishlistitemUrl)
.pipe(
map((result: any[]) => {
let wishItem: Wish[]= [];
for(let item of result) {
let productExists = false
if (!productExists){
wishItem.push(new Wish(item.id, item.name, item.description,
item.price, item.imageUrl);
}
}
return wishItem;
})
);
}
addProductToWishlistItem(product:Wish):Observable<any>{
return this.http.post(wishlistitemUrl, {product});
}
}
//Here is wishlistitem
import { Component, Input, OnInit } from '#angular/core';
import { ProductService } from 'src/app/services/product.service'
import { WishlistService } from 'src/app/services/wishlist.service';
import { WishlistItemService } from '#app/services/wishlist-item.service';
import { MessengerService } from 'src/app/services/messenger.service';
import { map } from 'rxjs/operators';
import { Wish } from '#app/models/wish';
import { Product } from '#app/models/product';
#Component({
selector: 'app-wishlistitem',
templateUrl: './wishlistitem.component.html',
styleUrls: ['./wishlistitem.component.scss']
})
export class WishlistitemComponent implements OnInit {
#Input() wishitemItem: Wish
#Input() productItem: Product
#Input() product: string
constructor(private wishlistService: WishlistService, private _wishlistitemService:
WishlistItemService, private msg:MessengerService ) { }
ngOnInit(): void {
}
//This function works as expected
handleAddToWishlistitem(){
this._wishlistitemService.addProductToWishlistItem (this.wishitemItem).subscribe(()
=>{
alert("Get wish list item");
this.msg.sendMsg(this.wishitemItem)
})
}
}
//Here is wishlistitem Html
<p>wishlistitem works!</p>
<div class="test">
<div class="container" style="margin:0 auto">
<div class="row no-gutters" style="margin-top: 30px">
<div class="col-4">
<img class="shacker" [src]="wishitemItem.imageUrl" />
<div class="card-body">
<p class="card-text" style="text-align:left; width:130px">
{{wishitemItem.name}}</p>
<p class="card-text" style="text-align:left; width:130px;">
<strong>{{ wishitemItem.price | currency }}</strong>
</p>
<p class="card-text" style="text-align:left; width: 150px">
{{wishitemItem.description | slice: 0:20}}...</p>
</div>
</div>
</div>
</div>
</div>
//I hope the explanation is sufficient. I have tried many scenarios, the issue I'm
having is with the property for the wishlist item, carItem does not have a property
and when I create one the application doesn't behave as expected.
Thank you in advance
PDH

Angular service not passing form data after routing

New to Angular and I feel like there's just an obvious mistake I am missing, code-wise.
I'm trying to follow the tutorial here: https://youtu.be/CUAHJxWGia0
I have one component to create/add an employee's ID called CreateEmployee.
On submission, it should route to a component to list all employees (ListEmployees).
It's using employee.service.ts.
When I click submit (before or without routing), it correctly logs the employee input to the console on CreateEmployee.
The problem is that when routing to the second component, ListEmployees, my new entry is not displayed at all, and only my test data is displayed.
I've made sure EmployeeService is included in my app.module as well.
create-employee.ts:
import { Component, OnInit } from '#angular/core'
import { FormControl, FormBuilder, NgForm } from '#angular/forms'
import { EmployeeService } from 'app/services/employee.service'
import { Router } from '#angular/router'
import { Employee } from 'app/shared/employee.model'
#Component({
selector: 'app-create-employee',
template: ` <form class="" [formGroup]="employeeForm" (ngSubmit)="saveEmployee()">
<div class="form-control">
<app-input
#memberID
name="memberID"
label="Member ID"
formControlName="memberID"
placeholder="Member ID"
></app-input>
</div>
<div><button type="submit" class="">Save</button></div>
</form>
{{ employeeForm.value | json }}
`,
styleUrls: ['./create-employee.component.scss'],
})
export class CreateEmployeeComponent implements OnInit {
employeeForm: any
constructor(private fb: FormBuilder, private _employeeService: EmployeeService, private _router: Router) {}
employee: Employee = {
memberID: null,
}
ngOnInit(): void {
this.employeeForm = this.fb.group({
memberID: new FormControl(''),
})
this.employee = this.employeeForm.get('memberID').value
}
saveEmployee() {
this._employeeService.save(this.employee)
console.log(this.employeeForm.get('memberID').value)
// this._router.navigate(['employee-list'])
}
}
list-employee.ts
import { Component, OnInit } from '#angular/core'
import { Employee } from 'app/shared/employee.model'
import { EmployeeService } from 'app/services/employee.service'
#Component({
selector: 'app-list-employees',
template: `<div *ngFor="let employee of employees">
<div class="">
{{ employee.memberID }}
</div>
</div> `,
styleUrls: ['./list-employees.component.scss'],
})
export class ListEmployeesComponent implements OnInit {
employees: Employee[] = []
constructor(private _employeeService: EmployeeService) {}
ngOnInit(): void {
this.employees = this._employeeService.getEmployees()
}
}
employee.service.ts
import { Injectable } from '#angular/core'
import { Employee } from 'app/shared/employee.model'
#Injectable({
providedIn: 'root',
})
export class EmployeeService {
listEmployees: Employee[] = [{ memberID: '1' }, { memberID: '2' }]
constructor() {}
getEmployees(): Employee[] {
return this.listEmployees
}
save(employee: Employee) {
this.listEmployees.push(employee)
}
}

Can't read url as JSON data

I have this JSON data and I'm getting it's output to a html file using angular. I use a service to get JSON data and a component to create the template. After using the template, I'm getting only id value and name value, but not url value.
JSON:
{
"A":1,
"B":[
{
"id":1,
"name":"One",
"url":"http://myapp/rootpath/first"
},
{
"id":2,
"name":"two",
"url":"http://myapp/rootpath/second"
}
]
}
I'm taking the JSON data to postArray variable in the component and pass it to the html file.
search.service.ts:
import { Injectable } from '#angular/core';
import {Http,Response} from "#angular/http";
import { Observable } from "rxjs";
import "rxjs/Rx";
import {JsoncallItem} from "./jsoncall-item";
#Injectable({
providedIn: 'root'
})
export class ApiService {
private postsURL ="http://myapp/items";
constructor(private http: Http ) {}
getPosts(): Observable<JsoncallItem[]>{
return this.http
.get(this.postsURL)
.map((response: Response)=> {
return <JsoncallItem[]>response.json();
})
.catch(this.handleError);
}
private handleError(error: Response) {
return Observable.throw(error.statusText);
}
}
search.component.ts
import { Component, OnInit } from '#angular/core';
import { ApiService } from "./../search.service";
import { JsoncallItem } from "./../jsoncall-item";
import { error } from 'util';
import { SearchtermPipe } from './../searchterm.pipe';
#Component({
selector: 'app-search',
templateUrl: './search.component.html',
styleUrls: ['./search.component.css']
})
export class SearchComponent implements OnInit {
title = 'app';
_postsArray: JsoncallItem[];
constructor(private apiSerivce: ApiService){}
getPosts(): void {
this.apiSerivce.getPosts().
subscribe(
resultArray => this._postsArray = resultArray
)
//error => console.log("Error :: " + error ))
}
ngOnInit(): void{
this.getPosts();
}
}
search.component.html:
<div class="container">
<ul>
<li *ngFor="let post of _postsArray | searchterm: value">
{{post.id}}, {{post.name}}, {{post.url}}
<hr>
</li>
</ul>
</div>
Output shows the id and name of each data, but not showing the url. What could be the wrong here?

Parent / Child component communication angular 2

I am failing to implement action button in child_1 component but the event handler is in sub child component child_2 as shown in the following code:
app.component.html (Parent Html)
<div style="text-align:center">
<h1>
Welcome to {{title}}!
</h1>
<app-navigation></app-navigation> <!-- Child1-->
</div>
app.component.html (Parent Component)
import { Component } from '#angular/core';
import { ProductService } from './productservice';
import {Product} from './product';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
title = 'MobileShirtShoeApp';
}
app.module.ts (Main Module)
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpModule } from '#angular/http';
import { Product } from './product';
import { ProductService } from './productservice';
import { AppComponent } from './app.component';
import { NavigationComponent } from './navigation/navigation.component';
import { DataTemplateComponent } from './data-template/data-template.component';
#NgModule({
declarations: [AppComponent,NavigationComponent,DataTemplateComponent],
imports: [BrowserModule,HttpModule],
providers: [ProductService],
bootstrap: [AppComponent]
})
export class AppModule { }
navigation.component.html (Child 1 HTML)
<fieldset>
<legend>Navigate</legend>
<div>
<button (click)="loadMobiles()">Mobiles</button> <!--Child_1 Action-->
</div>
<app-data-template></app-data-template>
</fieldset>
navigation.component.ts (Child 1 Component.ts)
import { Component, OnInit } from '#angular/core';
import { ProductService } from '../productservice';
import {Product} from '../product';
import {DataTemplateComponent} from '../data-template/data-template.component';
#Component({
selector: 'app-navigation',
templateUrl: './navigation.component.html',
styleUrls: ['./navigation.component.css']
})
export class NavigationComponent implements OnInit {
error: string;
productArray: Product[];
constructor(private myService: ProductService){
this.myService = myService;
}
dataTemplateComponent: DataTemplateComponent = new DataTemplateComponent(this.myService);
ngOnInit() {
}
loadMobiles() {
return this.dataTemplateComponent.loadMobiles();
}
}
data-template.component.html (Child 2 HTML) (NOT DISPLAYING DATA)
<fieldset>
<legend>Requested Data</legend>
Welcome
<div>
<ul>
<li *ngFor="let product of productArray">
{{product.id}} {{product.name}} {{product.price}}
<img src="{{product.url}}">
</li>
</ul>
</div>
</fieldset>
data-template.component.ts (Child 2 Component) (Contains Product service calling code)
import { Component} from '#angular/core';
import {Product} from '../product';
import {ProductService} from '../productservice';
#Component({
selector: 'app-data-template',
templateUrl: './data-template.component.html',
styleUrls: ['./data-template.component.css']
})
export class DataTemplateComponent {
error: string;
productArray: Product[];
constructor(private productService: ProductService) {
this.productService = productService;
}
loadMobiles(){
let promise = this.productService.fetchMobiles();
promise.then(productArr => {
return this.productArray = productArr;
}).catch((err) => {
this.error = err;
});
}
}
ProductService.ts
import 'rxjs/add/operator/toPromise';
import {Http, HttpModule} from '#angular/http';
import {Injectable} from '#angular/core';
import {Product} from './product';
#Injectable()
export class ProductService{
http: Http;
constructor(http: Http){
this.http = http;
console.log(http);
}
fetchMobiles(): Promise<Product[]>{
let url = "https://raw.githubusercontent.com/xxxxx/Other/master/JsonData/MobileData.json";
return this.http.get(url).toPromise().then((response) => {
return response.json().mobiles as Product[];
}).catch(this.handleError);
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error);
return Promise.reject(error.message || error);
}
}
Sorry if the code bothers you. So basically i am failing to display service data in child_2.html when an action made in child_1.html.The service working fine and name is ProductService which uses Product.ts as an object to get the data in JSON format. Any kind of help is appreciated.
This doesn't work because the DataTemplateComponent you're instantiating in app-navigation isn't the same instance of DataTemplateComponent as the one on the page. It's a brand new one that you instantiated and that isn't bound to the page at all. What you're trying to achieve is component communication. Specifically, parent / child component communication. There are a number of ways to do this, the cleanest and most flexible / extensible way is with a shared service pattern. Basically, you declare a service with an observable in it that you inject into both services and one updates the observable while the other is subscribed to it, like this:
#Inject()
export class MyComponentCommunicationService {
private commSubject: Subject<any> = new Subject();
comm$: Observable<any> = this.commSubject.asObservable();
notify() {
this.commSubject.next();
}
}
Then provide this service, either at the app module or possibly at the parent component depending on needs then in app navigation:
constructor(private commService: MyComponentCommunicationService) {}
loadMobiles() {
this.commservice.notify();
}
and in data template:
constructor(private commService: MyComponentCommunicationService, private productService: ProductService) {}
ngOnInit() {
this.commSub = this.commService.comm$.subscribe(e => this.loadMobiles());
}
ngOnDestroy() { this.commSub.unsubscribe(); } // always clean subscriptions
This is probably a little unneccessary since you already have the product service there. You could probably just move the load mobiles logic into the product service and have that trigger an observable that the data template service is subscribed to, and have the nav component call the load mobile method on the product service, but this is just meant to illustrate the concept.
I'd probably do it like this:
#Inject()
export class ProductService {
private productSubject: Subject<Product[]> = new Subject<Product[]>();
products$: Observable<Product[]> = this.productSubject.asObservable();
loadMobiles() {
this.fetchMobiles().then(productArr => {
this.productSubject.next(productArr);
}).catch((err) => {
this.productSubject.error(err);
});
}
}
then nav component:
loadMobiles() {
this.myService.loadMobiles();
}
then data template:
ngOnInit() {
this.productSub = this.productService.products$.subscribe(
products => this.productArray = products,
err => this.error = err
);
}
ngOnDestroy() { this.productSub.unsubscribe(); } // always clean subscriptions

Async data handling in Angular

I'm trying to load a local JSON into my component, but I can't get the values from my service into my component. I can see the json data in the service but it is undefined in my component. Does anybody see what i'm doing wrong here ? Thanks.
Here is an SS of the console.log in both service and component
interfaces.json
{
"interfaces": {
"eth" : {"name" : "eth"},
"lte" : {"name" : "lte"},
"wlc" : {"name" : "wlc"},
"wlap" : {"name" : "wlap"}
}
}
interfaces.service.ts
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
#Injectable()
export class Interfaces {
constructor(public http: Http) {};
public getData() {
return this.http.get('/assets/interfaces.json')
.map((res) => {res.json(); console.log(res); });
};
}
interfaces.component.ts
import { Component, OnInit } from '#angular/core';
import { Interfaces } from './interfaces.service';
import { Observable } from 'rxjs/Rx';
#Component({
selector: 'interfaces',
providers: [
Interfaces
],
template: `
<ul *dropdownMenu class="dropdown-menu" role="menu">
<li *ngFor="let interface of interfaces | async" role="menuitem">
<a [routerLink]=" ['./interfaces/eth'] "routerLinkActive="active"
[routerLinkActiveOptions]= "{exact: true}" class="dropdown-item" href="#">
{{interface.name}}Main Ethernet
</a>
</li>
</ul>
`,
})
export class InterfacesComponent implements OnInit {
constructor(public interfaces: Interfaces) {}
public ngOnInit() {
this.interfaces.getData().subscribe((data) => { this.data = data; console.log(data); });
}
}
The reason that it's undefined is that you are not returning your response inside the map not that map is not working..
.map((res) => {console.log(res); return res.json(); }); // missing return here
or without brackets:
.map((res) => res.json());
I don't know what is wrong as I'm new to angular2, but this works for me.
interfaces.service.ts
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
#Injectable()
export class Interfaces {
constructor(public http: Http) {};
public getData() {
return this.http.get('/assets/interfaces.json');
}
}
interfaces.component.ts
import { Component, OnInit } from '#angular/core';
import { Interfaces } from './interfaces.service';
import { Observable } from 'rxjs/Rx';
export class InterfacesComponent implements OnInit {
constructor(public interfaces: Interfaces) {}
public ngOnInit() {
this.interfaces.getData().subscribe((data) => {
this.data = data;
console.log(data);
});
}
}