MEAN stack delete request has 404 not found error - node.js

My post request and list all request are working fine, but I have problem getting my delete request to work. I have tested in Postman, but still have error. I think my delete url is fine, I can console log and see the item id been selected and show at the end of the url when making the request, I don't know what 's wrong.
delete.component.ts
deleteItem(): void {
console.log(this.currentItem._id);
alert("You had redeemed free food "+this.currentItem.itemToDonate);
this.charityService.deleteItem(this.currentItem._id).subscribe(
() => console.log("All of this food item has been redeemed"),
(err) => console.log(err)
)
}
charity.service.ts
import { Injectable } from '#angular/core';
import { HttpClient, HttpParams, HttpHeaders } from '#angular/common/http';
import { Observable, throwError } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { identifierModuleUrl } from '#angular/compiler';
//import { DonateComponent } from '../donate/donate.component';
const AUTH_API = 'http://localhost:3000/api/auth/donate';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json'})
};
#Injectable({
providedIn: 'root'
})
//post new donates to the database, list all items on the beneficiary page
//update quantity after redeem, delete item if the quantity is 0
export class CharityService {
constructor(private http: HttpClient) { }
donate(itemToDonate: string, quantity: number): Observable<any> {
return this.http.post(AUTH_API, {
itemToDonate, quantity
}, httpOptions);
}
listItem(): Observable<any> {
return this.http.get(AUTH_API, {});
}
receive(id: string): Observable<any> {
return this.http.put(`${AUTH_API}/update/${id}`, httpOptions)
.pipe(
catchError((err, caught) => {
console.error(err);
throw err;
})
);
}
getItem(id: string): Observable<any> {
return this.http.get(`${AUTH_API}/${id}`);
}
deleteItem(id: string): Observable<any> {
return this.http.delete(`${AUTH_API}/${id}`)
}
}
route.js
const controller_donate = require("../controllers/donate.controller");
const controller_receive = require("../controllers/receive.controller");
const controller_list = require("../controllers/list.controller");
const controller_delete = require("../controllers/delete.controller");
module.exports = function(app) {
app.use(function(req, res, next) {
res.header(
"Access-Control-Allow-Headers",
"x-access-token, Origin, Content-Type, Accept"
);
next();
});
app.post("/api/auth/donate", controller_donate.donate);
app.get("/api/auth/donate", controller_list.donations);
app.put("/api/auth/donate/update/:id", controller_receive.receive);
app.delete("/api/auth/donate/:id", controller_delete.delete);
};
delete.controller.js
const db = require("../models");
const Donate = db.donate;
const { donate } = require("../models");
exports.delete = (req, res) => {
const id = req.params.id;
donate.findByIdAndRemove(id)
.then(data => {
if (!data) {
res.status(404).send({ message: "Cannot delete item" });
} else {
res.status(200).send("This item is been redeemed");
}
})
}

Related

IONIC post method is returning undefined value

ERROR MESSAGE
I tested the node js post on postman and it worked. However, when I made use of ionic serve, it will show the error as shown in the image above. This error occurred when I call the makePayment() function in the stripe.page.ts file. The data I retrieved through this.checkout.makePayment in the makePayment() function returns undefined. I am guessing that the issue is probably my node js isn't being triggered when I use ionic serve. Is there a way to solve this?
THIS IS MY checkout.service.ts FILE
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class CheckoutService {
constructor(private http: HttpClient) { }
makePayment(stripeToken: any): Observable<any>{
const url = "http://localhost:5040/checkout"
return this.http.post<any>(url,{token:stripeToken})
}
}
THIS IS MY index.js FILE
const express = require("express");
const bodyparser = require('body-parser')
const app = express();
app.use(bodyparser.urlencoded({ extended: false }))
app.use(bodyparser.json())
const stripe = require("stripe")("###SECRETKEY###");
const cors = require('cors')
app.use(cors())
app.post('/checkout', function(req, res) {
try {
console.log(req.body);
token = req.body.token
const customer = stripe.customers
.create({
email: "cycoplayz#gmail.com",
source: token.id
})
.then((customer) => {
console.log(customer);
return stripe.charges.create({
amount: 1000,
description: "Test Purchase using express and Node",
currency: "USD",
customer: customer.id,
});
})
.then((charge) => {
console.log(charge);
res.json({
data:"success"
})
})
.catch((err) => {
res.json({
data: "failure",
});
});
return true;
} catch (error) {
return false;
}
})
app.listen(5040, () => {
console.log("App is listening on Port 5040")
})
THIS IS MY stripe.page.ts FILE
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute } from '#angular/router';
import { Loan } from '../shared/loan';
import { LoanService } from '../shared/loan.service';
import { ChargeInfo } from '../shared/models/chargeinfo';
import { CheckoutService } from '../shared/services/checkout.service';
#Component({
selector: 'app-stripe',
templateUrl: './stripe.page.html',
styleUrls: ['./stripe.page.scss'],
})
export class StripePage implements OnInit {
paymentHandler: any = null;
success: boolean = false
failure:boolean = false
loan: Loan;
loanid: string;
reason: string;
amount: number;
payment: number;
charged: ChargeInfo[] = [];
constructor(private checkout: CheckoutService, private route: ActivatedRoute, private
loanService: LoanService) {
this.loanid = this.route.snapshot.params.id
this.loanService.getChargesById(this.loanid)
.then(data =>{
this.reason = data.charges[0].reason;
this.amount = data.charges[0].amount;
})
}
ngOnInit() {
this.invokeStripe();
}
makePayment(amount: number) {
const paymentstripe = (stripeToken: any) => {
try{
this.checkout.makePayment(stripeToken).subscribe((data: any) => {
console.log(data);
if (data.data === "success") {
this.success = true
}
else {
this.failure = true
}
});
}
catch(err){
console.log(err);
console.log("hi");
}
};
const paymentHandler = (<any>window).StripeCheckout.configure({
key: '###PUBLISHABLE KEY###',
locale: 'auto',
token: function (stripeToken: any) {
console.log(stripeToken);
console.log(this.checkout.makePayment);
console.log(this.checkout.omg)
paymentstripe(stripeToken);
},
});
paymentHandler.open({
name: 'CHARGES',
description: this.reason,
amount: this.amount * 100,
});
}
invokeStripe() {
if (!window.document.getElementById('stripe-script')) {
const script = window.document.createElement('script');
script.id = 'stripe-script';
script.type = 'text/javascript';
script.src = 'https://checkout.stripe.com/checkout.js';
script.onload = () => {
this.paymentHandler = (<any>window).StripeCheckout.configure({
key: '###PUBLISHABLE KEY###',
locale: 'auto',
token: function (stripeToken: any) {
console.log(stripeToken);
},
});
};
window.document.body.appendChild(script);
}
}
}

TypeError: Cannot read properties of undefined (reading 'length') while using Interceptor

I have the following Angular and Node JS as follows
Interceptor
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from "#angular/common/http";
import { Injectable } from "#angular/core";
import { Observable } from "rxjs";
import { AuthService } from "../Services/auth.service";
#Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private authService : AuthService) {}
intercept(req: HttpRequest<any>, next: HttpHandler) {
//console.log(this.authService.getAuthToken())
const authToken = this.authService.getAuthToken();
const authRequest = req.clone({
headers: req.headers.set("Authorization", authToken)
});
console.log("authRequest");
return next.handle(authRequest);
}
}
service
import { HttpClient } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { api_url } from '../Models/global-url.model';
import { LoginModel } from '../Models/login_details.model';
import { ResponseFromServer } from '../Models/response.model';
#Injectable({
providedIn: 'root'
})
export class AuthService {
private token : string;
//Password is asish for all users
constructor(private http: HttpClient) { }
checkUserLogin(loginDetails: LoginModel) {
console.log(loginDetails);
this.http.post<{response: any}>(api_url+"login/loginUser", loginDetails).subscribe((result: ResponseFromServer) => {
console.log(result.token);
this.token = result.token;
console.log(this.token);
});
}
getAuthToken() {
return this.token;
}
}
User Defined Middleware in Node JS :-
const jwt = require('jsonwebtoken');
const s_token = require('../tokens/auth-token');
//const authFunction = (req, res, next) => {
module.exports = (req, res, next) => {
console.log(req);
var message = '';
try {
const token = req.headers.authorization;
console.log(token);
jwt.verify(token, s_token);
next();
} catch (err) {
message = "Auth Failed";
console.log(err); //JsonWebTokenError: Error jwt must be provided => user is not logged in
res.status(401).json(message);
// res.json(message); //Check the error message that occurs in browser console, while using this without status
}
}
login.js in Node Router :-
router.post('/loginUser', async (req, res, next) => {
const loginDetails = req.body;
console.log(loginDetails);
var { userId, stored_password,userEmailId,token,status_code } = '';
var message = '';
var response = '';
//console.log(loginDetails);
query = `SELECT * FROM tbl_users WHERE (tum_email = $1 OR tum_mobile = $1)`;
params = [loginDetails.username];
// await db.query(query, params, (err, result) => {
// if(err) {
// console.log(err);
// response = 'f0';
// message = "Internal Server Error. Please reload the page and try again.";
// } else if(result.rows.length) {
// //console.log(result.rows.length);
// userId = result.rows[0].tum_email;
// password = result.rows[0].tum_password;
// response = 's1';
// message = "";
// } else {
// response = 'f1';
// message = "User with the given user id does not exist. Please register here";
// }
// });
try {
const result = await db.query(query, params);
if(result.rowCount == 0 ) {
response = 'f1';
message = "User with the given user id does not exist. Please register here";
} else {
userId = result.rows[0].tum_id;
userEmailId = result.rows[0].tum_id;
stored_password = result.rows[0].tum_password;
try {
if ((await argon2.verify(stored_password, loginDetails.password))) {
//password matches
response = 'success';
const session_data = {
userId: userId,
email: userEmailId
}
token = jwt.sign(session_data, s_token, {expiresIn:'1hr'});
//console.log(token);
} else {
response = 'f2';
message = "Entered password is wrong. Please enter the correct password, or reset it";
}
} catch (err) {
console.log(err);
response = 'f0';
message = "Internal Server Error. Please reload the page and try again, or contact an Administrator";
}
}
} catch (err) {
console.log(err);
response = 'f0';
message = "Internal Server Error. Please reload the page and try again, or contact an Administrator";
}
const json_object = {
token: token,
response: response,
message:message
}
if(token != '') {
status_code = 200;
} else {
status_code = 401;
}
res.status(status_code).json(json_object);
//console.log("response ="+response+" & message = "+ message);
});
login.component.ts
import { Component, OnInit } from '#angular/core';
import { NgForm } from '#angular/forms';
import { AuthData } from 'src/app/Models/auth_data.model';
import { LoginModel } from 'src/app/Models/login_details.model';
import { ResponseFromServer } from 'src/app/Models/response.model';
import { AuthService } from 'src/app/Services/auth.service';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
isSubmitted = false;
isValid = true;
isLoading = false;
response_from_server = new ResponseFromServer();
constructor(private authService: AuthService) {
}
ngOnInit(): void {
this.response_from_server.response = 's1';
}
loginUser(loginData: NgForm) {
this.isSubmitted = true;
if(loginData.invalid) {
this.isValid = false;
//console.log("Validation Errors");
return;
}
const loginDetails : LoginModel = {
username : loginData.value.username,
password: loginData.value.password
}
this.authService.checkUserLogin(loginDetails);
}
}
Whenever I try to login , the error TypeError: Cannot read properties of undefined (reading 'length') is thrown.
The data is not even sent to the server side. It is stuck before return next.handle(authRequest);.
I tried console.log() almost everywhere to see where I am getting the mistake, and to which part, the data movement is getting done. Looks like the email and password are not even going through, to the Node JS server. Using console.log(result.token) in login.service.ts does not have any value.
Where am I going wrong ?
The problem is most likely happening because your trying to add the Authorization header before the user is logged-in.
In that situation authToken is undefined and you are assigning it to the header anyways.
You could solve it just adding a guard in your intercept method to first check if you have an authToken before attaching it to the request.
intercept(req: HttpRequest<any>, next: HttpHandler) {
const authToken = this.authService.getAuthToken();
if(!authToken) { // <--- not logged-in skip adding the header
return next.handle(req);
}
const authRequest = req.clone({
headers: req.headers.set("Authorization", authToken)
});
return next.handle(authRequest);
}
Cheers

Angular: JWT Token works fine on Postman but not in my app

I'm a bit of a beginner with Angular so please bear with me.
I have a simple app which allows people to register, login and retrieve their own user data (which is the part I am stuck at).
Backend user.routes.js :
const auth = require('./middlewares/auth')
module.exports = (app) => {
const user = require('./user.controller.js');
app.post('/login', user.login);
app.post('/register', user.register);
app.get('/getuser', auth, user.getuser);
}
Backend user.controller.js:
exports.getuser = async (req, res, next) => {
let user
try {
user = await User.findById(req.payload._id)
} catch (err) {
next(new InternalServerError('Could not fetch user', err))
return
}
if (!user) {
next(new NotFoundError('User not found'))
return
}
res.json(
pick(user, [
'email',
'firstName',
'lastName',
'accountType'
])
)
}
Backend user.service.ts :
#Injectable()
export class UserService {
private _isLoggedIn: BehaviorSubject<boolean> = new BehaviorSubject(false);
public readonly isLoggedIn$ = this._isLoggedIn.asObservable();
constructor(private http: HttpClient) {
this._isLoggedIn.next(this.isLoggedIn());
}
login(
email: string,
password: string,
rememberMe = false
): Observable<boolean | any> {
return this.http
.post<LoginResponse>('http://localhost:3001/login', { email, password })
.map(res => {
setToken(res.token, rememberMe);
this._isLoggedIn.next(true);
return true;
})
.catch(this.handleError);
}
register(
email: string,
password: string,
lastName: string,
firstName: string
): Observable<boolean | any> {
return this.http
.post<LoginResponse>('http://localhost:3001/register', {
email,
password,
lastName,
firstName
})
.map(res => {
setToken(res.token);
return true;
})
.catch(this.handleError);
}
logout() {
removeToken();
}
isLoggedIn() {
return tokenNotExpired();
}
getProfile() {
return this.http.get<Profile>('http://localhost:3001/getuser');
}
And finally, my backend auth.js :
// Dependencies
import { JwtHelperService } from '#auth0/angular-jwt';
// Angular
import {
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest
} from '#angular/common/http';
import { Injectable } from '#angular/core';
// RXJS
import { Observable } from 'rxjs/Observable';
// Environment
import { DecodedToken } from './decoded-token';
// Services
const helper = new JwtHelperService();
// Constants
export const TOKEN_NAME = 'access_token';
// Exports
export function getToken(storage = null) {
if (storage) {
const token = storage.getItem(TOKEN_NAME);
if (token && !helper.isTokenExpired(token)) {
return token;
}
removeToken(storage);
return null;
}
return getToken(localStorage) || getToken(sessionStorage);
}
export function setToken(token: string, rememberMe = false) {
const storage = rememberMe ? localStorage : sessionStorage;
storage.setItem(TOKEN_NAME, token);
}
export function removeToken(storage = null) {
if (storage) {
storage.removeItem(TOKEN_NAME);
} else {
localStorage.removeItem(TOKEN_NAME);
sessionStorage.removeItem(TOKEN_NAME);
}
}
export function tokenNotExpired() {
return !helper.isTokenExpired(getToken());
}
export function decodeToken(): DecodedToken {
return helper.decodeToken(getToken());
}
#Injectable()
export class JwtHttpInterceptor implements HttpInterceptor {
constructor() {}
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
const token = getToken();
let clone: HttpRequest<any>;
if (token) {
clone = request.clone({
setHeaders: {
Accept: `application/json`,
'Content-Type': `application/json`,
Authorization: `Bearer ${token}`
}
});
} else {
clone = request.clone({
setHeaders: {
Accept: `application/json`,
'Content-Type': `application/json`
}
});
}
return next.handle(clone);
}
}
On my dashboard, I do a very simple request:
this.userService.getProfile().subscribe(data => (this.profile = data));
Now, my problem is the following:
Using Postman, if I do a POST request to /login, I get a token back. Everything fine so far. And if I use this token (in Postman) in my next GET request to /getuser, I also get the results I want (email, firstName, lastName, accountType of the user).
However, the problem is on the front-end. I login and arrive to the main page (no issues there), but once getProfile() is called, I get a GET http://localhost:3001/getuser 401 (Unauthorized) . I've been stuck on this for hours and not sure where the problem is from.
I appreciate any help I can get.
Thanks!
I found my issue. I had forgotten to add the Interceptor I had created to my providers in app.module.ts.
// Auth
{
provide: HTTP_INTERCEPTORS,
useClass: JwtHttpInterceptor,
multi: true
}

Get Large Set of Data (~20000 item) from mongodb and display it in angular 7 Admin Products Page

I'm trying to get ~20000 items from Mongodb and display them at my Angular 7 Project in Admin Products Page in a table
The Problem is that the website takes too much time and sometimes it crashes
Is there a way to get them as 1000 item after another, get them fastly, or paginate them as 0-1000 item in a page 1 and 1000-2000 in page 2?
I searched for it and I didn't find any useful resource or even a similar question here.
I found that I could limit number of get items in mongodb through this code:
ITEMS_COLLECTION.find({}).limit(1000).toArray((err, allItems) => {
items = allItems
})
I don't want to just limit it to 1000, I want get all of them and display them without crashing the browser or not to be so slow.
This is the Item Page: src > Item.js
function getItems() {
let items
Server().then((server_data) => {
server_data.ITEMS_COLLECTION.find({}).limit(1000).toArray((err, allItems) => {
items = allItems
})
})
/*eslint no-undef: 0*/
return new Promise(resolve => {
setTimeout(() => {
resolve(items)
}, 4000)
})
}
This is the server page: src > server.js
app.get('/activeProducts', (req, res) => {
Item.getActiveItems()
.then(active_items => {
res.send(active_items);
})
.catch(err => {
throw new CustomError('Could not get Active Items', err);
});
});
This is the Products Service:
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { LoginService } from './login.service';
import { Router } from '#angular/router';
import { MatDialog, MatDialogRef } from '#angular/material';
import { environment } from '../../environments/environment';
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
Authorization: 'my-auth-token'
})
};
#Injectable()
export class ProductsService {
products = this.http.get(
` ${environment.link_url_with_backend}/activeProducts`
);
cached_products;
constructor(
private loginService: LoginService,
private router: Router,
private http: HttpClient,
public dialogRef: MatDialog
) {
this.products.subscribe(data => {
console.log(data);
this.cached_products = data;
});
}
}
This is the Products Component:
export class ProductsComponent implements OnInit, DoCheck {
constructor(private productService: ProductsService) {}
products;
ngOnInit() {
this.products = this.productService.cached_products;
}
}
This is the Products HTML:
<div
class="products-container wrapper"
>
<app-product
*ngFor="let product of products"
[product]="product"
style="width: 360px;"
></app-product>
</div>
First of All In The Backend you need to get the first 100 for example:
function getFirst100Items() {
let items
ITEMS_COLLECTION
.find({})
.limit(100)
.sort({id: 1})
.toArray( (err, allItems) => {
items = allItems
})
return new Promise(resolve => {
setTimeout(() => {
resolve(items)
}, 2000)
})
}
Then you can add load more function for example:
function getMore100Items(loadedItems) {
let items
server_data.ITEMS_COLLECTION
.find({ id: { $gte: loadedItems } })
.limit(100)
.sort({id: 1})
.toArray( (err, allItems) => {
items = allItems
})
return new Promise(resolve => {
setTimeout(() => {
resolve(items)
}, 2000)
})
}
function getItemsCount() {
let itemsCounts
server_data.ITEMS_COLLECTION.countDocuments()
.then( (counts) => {
itemsCounts = counts
})
return new Promise(resolve => {
setTimeout(() => {
resolve({itemsCounts})
}, 1000)
})
}
Then You Specify the express routes
app.get('/first/100products', (req, res) => {
Item.getFirst100Items()
.then(items => {
res.send(items);
})
.catch(err => {
throw new CustomError('Could not get Items', err);
});
});
app.post('/loadmore/products', (req, res) => {
loaded_items = req.body.loadedItems
res.send({loaded_items})
});
app.get('/loadmore/products', (req, res) => {
setTimeout(() => {
Item.getMore100Items(loaded_items)
.then(items => {
res.send(items);
})
.catch(err => {
throw new CustomError('Could not get Items', err);
});
}, 2000);
});
Second In Angular 7
Parent Component
loadedItems = 0;
#ViewChild(AdminTableComponent) adminTable;
constructor(public dialog: MatDialog, private http: HttpClient) {
this.http
.get(` ${environment.link_url_with_backend}/first/100products`)
.subscribe((data: {}[]) => {
this.products_data = data;
this.dataSource = new MatTableDataSource(this.products_data);
});
}
ngOnInit() {}
loadMore() {
this.http
.get(` ${environment.link_url_with_backend}/products/length`)
.subscribe((itemsCount: any) => {
if (this.loadedItems < itemsCount.itemsCounts - 100) {
this.adminTable.isLoad = true;
this.loadedItems += 100;
this.http
.post(
`${environment.link_url_with_backend}/loadmore/products`,
JSON.stringify({ loadedItems: this.loadedItems }),
httpOptions
)
.subscribe(data => {
console.log(data);
});
this.http
.get(` ${environment.link_url_with_backend}/loadmore/products`)
.subscribe((items: {}[]) => {
items.map(product => {
this.products_data.push(product);
this.dataSource = new MatTableDataSource(this.products_data);
this.adminTable.isLoad = false;
this.adminTable.dataSource.sort = this.adminTable.sort;
this.adminTable.dataSource.paginator = this.adminTable.paginator;
return;
});
});
} else {
this.adminTable.isLoad = false;
this.adminTable.isLoadMore = false;
alert('No More Products to Get');
return;
}
});
}
ChildComponent
loadMoreItems() {
this.loadMore.emit('loadMore');
}
#Input() dataSource;
#Input() displayedColumns;
#Input() dialogComponent;
#Output() loadMore = new EventEmitter();
isLoad = false;
isLoadMore = false;
And you can continue from here
Hope this helps!
Note: All this is just an example so don't take it exactly

MEAN stack: can't display data from a single Mongodb element by it's id

using a service and api to connect to I was able to display the whole array from my mongodb collection in catalog.component.ts :
api.js
const express = require('express');
const router=express.Router();
const app=express();
const MongoClient=require('mongodb').MongoClient;
const ObjectID=require('mongodb').ObjectID;
var path=require('path');
var db;
const connection=(closure) => {
return MongoClient.connect('mongodb://localhost:27017', (err, client)=>{
if (err) return console.log(err);
db=client.db('angulardb');
closure(db);
});
};
const sendError =(err, res)=>{
response.status=501;
response.message=typeof err == 'object' ? err.message : err;
res.status(501).json(response);
};
let response={
status:200,
data:[],
message: null
};
router.post('/getProducts',(req, res) => {
connection((db) => {
db.collection('products')
.find()
.toArray()
.catch((err)=>{
sendError(err, res);
response.message ={ success:"Se obtuvieron los registros correctamente", error:""};
res.send({response});
})
.then((result)=>{
response.data= result;
res.send({response});
});
});
});
router.post('/getProduct',(req, res) => {
connection((db) => {
db.collection('products')
.find({id:new ObjectID(req.query.id)})
.toArray()
.catch((err)=>{
sendError(err, res);
response.message ={ success:"Se obtuvieron los registros correctamente", error:""};
res.send({response});
})
.then((result)=>{
response.data= result;
res.send({response});
});
});
});
module.exports=router;
service where I added the getProducts function for catalog and getProduct function for details
mongo2.service.ts:
import { Injectable } from '#angular/core';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/toPromise';
import {HttpClient, HttpHeaders} from '#angular/common/http';
#Injectable()
export class Mongo2Service {
constructor( private _http: HttpClient) { }
getProducts() {
const headers = new HttpHeaders({'Content-Type': 'application/json' });
return this._http.post('/api/getProducts', { headers })
.catch( (error: any) => Observable.throw(error || 'server error'));
}
getProduct(id: number) {
const headers = new HttpHeaders({'Content-Type': 'application/json' });
const params = {'id': id};
return this._http.post('/api/getProduct', { headers, params})
.catch( (error: any) => Observable.throw(error || 'server error'));
}
}
Here I get the array from mongodb collection catalog.component.ts:
import { Component, OnInit } from '#angular/core';
import {Mongo2Service} from '../mongo2.service';
#Component({
selector: 'app-catalog',
templateUrl: './catalog.component.html',
styleUrls: ['./catalog.component.css']
})
export class CatalogComponent implements OnInit {
products: any;
respuesta: any;
constructor( private mongo2Service: Mongo2Service) {}
ngOnInit() {
this.getProducts();
}
getProducts() {
this.mongo2Service.getProducts().subscribe(respuesta => {
this.respuesta = respuesta;
this.products = this.respuesta.response.data;
console.log(this.respuesta);
});
}
}
And I get displayed the mongodb collecction
collection
in this list:
list
I add a router link to that list in catalog component with the selected element's id to another component called 'details' which has a 'getProduct' method in api and the service, but the view doesn't display the element's name or id:
import { Component, OnInit } from '#angular/core';
import {Location} from '#angular/common';
import {ActivatedRoute} from '#angular/router';
import {Mongo2Service} from '../mongo2.service';
#Component({
selector: 'app-details',
templateUrl: './details.component.html',
styleUrls: ['./details.component.css']
})
export class DetailsComponent implements OnInit {
respuesta: any;
products:any;
constructor(private location: Location,
private route: ActivatedRoute,
,private mongo2Service: Mongo2Service) { }
ngOnInit() {
this.getProduct();
}
getProduct() {
const id=+ this.route.snapshot.paramMap.get('_id');
console.log('entro funcion componente');
this.mongo2Service.getProduct(id).subscribe(respuesta => {
this.respuesta = respuesta;
this.products = this.respuesta.response.data;
console.log(this.respuesta);
});
}
goBack(): void{
this.location.back();
}
}
I solved it , I edited the getProduct method in api.js by changing req.query._id for req.body.id inside find.() as you can see:
router.post('/getProduct',(req, res) => {
var find={ id: new ObjectID(req.body.id) };
console.log(find);
connection((db) => {
db.collection('products')
.find({_id:new ObjectID(req.body.id)})
.toArray()
.catch((err)=>{
sendError(err, res);
response.message ={ success:"Se obtuvieron los registros correctamente", error:""};
res.send({response});
})
.then((result)=>{
response.data= result;
res.send({response});
});
});
});
I also deleted the '+' at the const id and added another variable (product:any) to the method in details with the position [0] in data.
getProduct() {
const id = this.route.snapshot.paramMap.get('_id');
console.log(id);
this.mongo2Service.getProduct(id).subscribe(respuesta => {
this.respuesta = respuesta;
this.product = this.respuesta.response.data[0];
console.log(this.respuesta);
});
}
MongoDB creates _id and not id, your match condition is wrong for getting the results.
I have updated the query and added the console log, check the console if you're getting expected result now.
router.post('/getProduct',(req, res) => {
connection((db) => {
db.collection('products')
.find({_id:new ObjectID(req.query.id)})
.toArray()
.catch((err)=>{
sendError(err, res);
response.message ={ success:"Se obtuvieron los registros correctamente", error:""};
res.send({response});
})
.then((result)=>{
console.log("Expected Results: ", result);
response.data= result;
res.send({response});
});
});
});
This should get you details for the single product. Check how you are using the returned data here.

Resources