how to read property 'subscribe' of undefined? - node.js

I have created a MEAN stack application which does the basic job of inserting,delete,update and viewing the data from mongoDB.
first of all i cloned this MEAN stack application from github. the application was based on the employee, but i renamed all the components, routing, etc from 'employee' to 'sensor'. what i have done literally is changed the word 'employee' to 'sensor'.
and i had not issues in compiling the code.
the build was successful.
but when i launched localhost:4200 , the first page was displayed properly,which is insert component. the data is inserted into mongodb. so this component has no issues.
but when i click on view sensor component,it shows a blank page.
so when i checked on chrome console by clicking on f12,it showed a list of errors.
please check for the errors in the below screenshot.4
the service.api code is below
import { Injectable } from '#angular/core';
import { throwError } from 'rxjs';
import { Observable } from 'rxjs/Observable';
import { catchError, map } from 'rxjs/operators';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class ApiService {
baseUri:string = 'http://localhost:4000/api';
headers = new HttpHeaders().set('Content-Type', 'application/json');
getSensors: any;
constructor(private http: HttpClient) { }
// Create
createSensor(data): Observable<any> {
let url = `${this.baseUri}/create`;
return this.http.post(url, data)
.pipe(
catchError(this.errorMgmt)
)
}
// Get Sensor
getSensor(id): Observable<any> {
let url = `${this.baseUri}/read/${id}`;
return this.http.get(url, {headers: this.headers}).pipe(
map((res: Response) => {
return res || {}
}),
catchError(this.errorMgmt)
)
}
// Update Sensor
updateSensor(id, data): Observable<any> {
let url = `${this.baseUri}/update/${id}`;
return this.http.put(url, data, { headers: this.headers }).pipe(
catchError(this.errorMgmt)
)
}
// Delete Sensor
deleteSensor(id): Observable<any> {
let url = `${this.baseUri}/delete/${id}`;
return this.http.delete(url, { headers: this.headers }).pipe(
catchError(this.errorMgmt)
)
}
// Error handling
errorMgmt(error: HttpErrorResponse) {
let errorMessage = '';
if (error.error instanceof ErrorEvent) {
// Get client-side error
errorMessage = error.error.message;
} else {
// Get server-side error
errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
}
console.log(errorMessage);
return throwError(errorMessage);
}
}
SENSOR-LIST.COMPONENT.TS is below
import { Component, OnInit } from '#angular/core';
import { ApiService } from './../../service/api.service';
#Component({
selector: 'app-Sensor-list',
templateUrl: './Sensor-list.component.html',
styleUrls: ['./Sensor-list.component.css']
})
export class SensorListComponent implements OnInit {
Sensor: any = [];
constructor(private apiService: ApiService) {
this.readSensor();
}
ngOnInit() {}
readSensor() {
this.apiService.getSensors.subscribe ((data) => {
this.Sensor = data;
});
}
removeSensor(Sensor, index) {
if (window.confirm('Are you sure?')) {
this.apiService.deleteSensor(Sensor._id).subscribe((data) => {
this.Sensor.splice(index, 1);
}
);
}
}
}
some of the screenshots
img 12
img 23
img 34
please help me out in this problem

getSensors is not a function first of all. You declared it in ApiService as a variable of type any. So if you want the list of sensors. Create the getSensors() method which will allow you to retrieve the list of sensors via the URL intended for it

Related

I am getting multiple calls from angular to the Post API in Node

I am trying to write a file from the data from the database but I'm getting multiple calls from the angular causing multiple entries of the same data.How can I stop that? And also it is causing to override write file after some time.
I am not getting what exactly should I do. I have tried subscribing thing in service in angular but it was of no help.
component.ts
import { Component, OnInit, ViewEncapsulation } from '#angular/core';
import { FormGroup, FormBuilder, Validators } from '#angular/forms';
import { NgbModalRef, NgbModal } from '#ng-bootstrap/ng-bootstrap';
import { ToastrService } from 'ngx-toastr';
import { CountryService } from './country.service';
import { ConfigService } from '../config.service';
#Component({
selector: 'app-country',
templateUrl: './country.component.html',
styleUrls: ['./country.component.scss'],
encapsulation: ViewEncapsulation.None,
providers: []
})
export class CountryComponent implements OnInit {
public modalRef: NgbModalRef;
public form: FormGroup;
public selectedCountry;
public countries;
constructor(public fb: FormBuilder, public toastrService: ToastrService,
public modalService: NgbModal, public configService: ConfigService,
public countryService: CountryService) {
}
ngOnInit() {
this.form = this.fb.group({
country: [null, Validators.compose([Validators.required])],
});
this.getCountries();
}
public getCountries() {
this.countryService.getCountries((data) => {
this.countries = data.countries;
}, (err) => { });
}
public selectCountry(country) {
this.countryService.selectCountry(country, (resp) => {
}, (err) => { });
}
}
service.ts
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '#angular/common/http';
import { ConfigService } from '../config.service';
import { ToastrService } from 'ngx-toastr';
#Injectable({
providedIn: 'root'
})
export class CountryService {
private setHeaders() {
const headers = new HttpHeaders({
'content-type': 'application/json',
});
return headers;
}
constructor(private configService: ConfigService, public http: HttpClient, public toastrService: ToastrService) { }
selectCountry(country: any, callback, errCallback) {
const options = {
headers: this.setHeaders(),
};
this.http.post(this.configService.url + '/selectedCountry', country, options).subscribe((resp: any) => {
callback(resp);
}, err => {
errCallback(err);
});
}
getCountries(callback, errCallback) {
const options = {
headers: this.setHeaders(),
};
this.http.get(this.configService.url + '/countries', options).subscribe((resp: any) => {
callback(resp.msg);
}, err => {
errCallback(err);
});
}
}
I want the call to be sent only once, not twice
Btw. - Please consider adding the NGRX lib in your app.
An angular-service is considered as a data holder. So make there an instance variable.
It could look like:
export class Service{
private countries;
...
public getCountries(){
return this.countries;
}
public loadCountries(){
this.http.get("url").subscribe(countries => this.countries = countries);
}
}
Then in your component class, you just get the countries.
export class Component{
public coutries;
...
public ngOnInit(){
this.countryService.getCountries(countries => this.countries=coutries);
}
}
And last but not least - load the countries in your AppComponent.
export class AppComponent{
...
public ngOnInit(){
this.countryService.loadCountries();
}
}
Need all your code if you can do a stackblitz, and like Mateusz said its better to handle state with ngrx if you dont want to call twice to backend or a simple approach its something like this https://stackblitz.com/edit/angular-biv6cw.
Change your service method like:
add interface:
export interface Country{
id: number;
name: string;
}
Change your method:
getCountries(): Observable<Country> {
return this.httpClient
.get('pass api url here')
.pipe(
map((body: any) => body),
catchError(error => of(error))
);
}
In your component:
ngOnInit() {
this.countryService.getCountries().subscribe(
(result: Countries) => {
this.countries = result;
},
err => {
log.debug('get countries error', err);
}
);
}
}
Try this:
// Somewhere on init
let postRequestCount = 0;
// More stuff …
// Just before doing the POST request inside the `selectCountry` method
if(postRequestCount < 1) {
http.post(); // TODO : Replace with the actual `post` method
}
postRequestCount++;

call a web service , by an action button with angular , from nodeJS server ,

want to call a rest API from a nodeJS server with a click of a button in my project angular to add a user in the database, the api in the server is connected to my mysql database , just i wonna invoke the api rest of add ou update ou delete from the button in my project angular . I am new to this I dont know how to proceed.
thank you
import { Component } from '#angular/core';
import { LocalDataSource } from 'ng2-smart-table';
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { SmartTableData } from '../../../#core/data/smart-table';
//import { EmailValidator } from '#angular/forms';
#Injectable()
export class ConfigService {
constructor(private http: HttpClient) { }
}
#Component({
selector: 'ngx-smart-table',
templateUrl: './smart-table.component.html',
styles: [`
nb-card {
transform: translate3d(0, 0, 0);
}
`],
})
#Injectable()
export class Configuration {
public server = 'http://localhost:3000/';
public apiUrl = 'api/';
public serverWithApiUrl = this.server + this.apiUrl;
}
export class SmartTableComponent {
settings = {
add: {
addButtonContent: '<i class="nb-plus"></i>',
createButtonContent: '<i class="nb-checkmark"></i>',
cancelButtonContent: '<i class="nb-close"></i>',
actionButonContent:'<i (click)="makeServiceCall($event)"><i/>',
},
edit: {
editButtonContent: '<i class="nb-edit"></i>',
saveButtonContent: '<i class="nb-checkmark"></i>',
cancelButtonContent: '<i class="nb-close"></i>',
actionButonContent:'<i (click)="onEditConfirm($event)"></i>'
},
delete: {
deleteButtonContent: '<i class="nb-trash"></i>',
confirmDelete: true,
actionButonContent:'<i (click)="onDeleteConfirm($event)"></i>'
},
columns: {
id: {
title: 'ID',
type: 'number',
},
firstName: {
title: ' Name',
type: 'string',
},
email: {
title: 'E-mail',
type: 'string',
},
password: {
title: 'password',
type: 'password',
},
},
};
source: LocalDataSource = new LocalDataSource();
constructor(private service: SmartTableData) {
const data = this.service.getData();
this.source.load(data);
}
onDeleteConfirm(event): void {
if (window.confirm('Are you sure you want to delete?')) {
event.confirm.resolve();
} else {
event.confirm.reject();
}
}
}
and this is my app.js (server)
var express = require('express');
var router = express.Router();
var user=require('../model/user');
router.get('/:id?',function(req,res,next){
if(req.params.id){
user.getUserById(req.params.id,function(err,rows){
if(err)
{
res.json(err);
}
else{
res.json(rows);
}
});
}
else{
user.getAllUsers(function(err,rows){
if(err)
{
res.json(err);
}
else
{
res.json(rows);
}
});
}
});
router.post('/',function(req,res,next){
user.addUser(req.body,function(err,count){
if(err)
{
res.json(err);
}
else{
res.json(req.body);
}
});
});
router.delete('/:id',function(req,res,next){
user.deleteUser(req.params.id,function(err,count){
if(err)
{
res.json(err);
}
else
{
res.json(count);
}
});
});
router.put('/:id',function(req,res,next){
user.updateUser(req.params.id,req.body,function(err,rows){
if(err)
{
res.json(err);
}
else
{
res.json(rows);
}
});
});
module.exports=router;
To make a call you need to add the HttpClientModule in your app.module.ts as import.
Then inject the Http client it wherever you want to use it:
constructor(private http: HttpClient){}
to use it just do:
this.http.get(<<url>>) //for get request
this.http.post(<<url>>,obj) //for post request
this returns an observable from which you can map the results and catch errors using Rxjs operators. for eg
addUser(user){ //called on button click
this.http.post(yourUrl,Json.Stringify(user)).pipe(
map((res)=>{
//do something with response
return 'sucess'
}),
catchError(err => {
//handleError
}
).subscribe(); // dont forget to subscribe
}
if you want to learn more : https://angular.io/guide/http
and for rxjs: https://www.learnrxjs.io/
Assume that the data that needs to be sent to the server is being passed to the function as the "data" parameter. Add "HttpClientModule" to the main app module or to your custom module if any as follows. Custom service has been imported in the app module or import it in your module accordingly.
app.module.ts
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { FormsModule } from '#angular/forms';
import { HttpClientModule } from '#angular/common/http';
import { CustomService } from 'location-of-custom-service';
#NgModule({
imports: [
CommonModule,
FormsModule,
HttpClientModule
],
declarations: [],
providers: [CustomService]
})
export class AppModule { }
Create a service file as follows.
custom.service.ts
import { Injectable } from '#angular/core';
import { Router } from '#angular/router';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Observable, throwError } from 'rxjs';
import { retry, catchError } from 'rxjs/operators';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
#Injectable({
providedIn: 'root'
})
export class CustomService {
public server = 'http://localhost:3000/';
public apiUrl = 'api/';
public serverWithApiUrl = this.server + this.apiUrl;
private fetchDataURL = this.serverWithApiUrl + 'fetchSomeData';
private addDataURL = this.serverWithApiUrl + 'addSomeData'
constructor(private _http: HttpClient) { }
// Fetch data
fetchData(id): Observable<any> {
this.fetchDataURL = this.fetchDataURL + "/" + id;
return this._http.get<any>(this.fetchDataURL, httpOptions)
.pipe(
retry(1),
catchError(this.handleError)
);
}
// Add data
addData(data): Observable<any> {
return this._http.post<any>(this.addDataURL, data, httpOptions);
}
// Error handler - you can customize this accordingly
handleError(error) {
let errorMessage = '';
if (error.error instanceof ErrorEvent) {
// client-side error
errorMessage = `Error: ${error.error.message}`;
} else {
// server-side error
errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
}
return throwError(errorMessage);
}
}
Your existing component has been modified so as to have the new additions as follows.
smarttable.component.ts
import { Component, OnInit } from '#angular/core';
import { Router, ActivatedRoute } from '#angular/router';
import { FormControl, FormGroup, Validators } from '#angular/forms';
import { CustomService } from './custom-service-location';
#Component({
selector: 'ngx-smart-table',
templateUrl: './smart-table.component.html'
})
export class SmartTableComponent implements OnInit {
constructor(private customService: CustomService) {}
fechedData: any;
// you existing codes goes here
// Add data - assume the data that needs to be sent to the server is as "data"
makeServiceCall(data) {
this.customService.addData(data)
.subscribe((data) => {
console.log(data);
// your logic after data addition goes here
},
(error) => {
// logic to handle error accordingly
});
}
// Fetch data
getData(id) {
this.customService.fetchData(id)
.subscribe((data) => {
console.log(data);
this.fechedData = data;
// your logic after data fetch goes here
},
(error) => {
// logic to handle error accordingly
});
}
}
I hope the above helps.

Angular 6 not getting response from expressjs node server

help a noob out, I am building a MEAN stack app and i ran into a problem where I cannot read a response from the express server but the response is generated when I use postman, here is my code
auth.service.ts
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import { map } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class AuthService {
authToken: any;
user: any;
constructor(private http:Http) { }
registerUser(user){
let headers = new Headers();
headers.append('Content-Type','application/json');
return this.http.post('http://localhost:3000/users/register',user,
{headers: headers})
.pipe(map(res => res.json));
}
authenticateUser(user){
let headers = new Headers();
headers.append('Content-Type','application/json');
return this.http.post('http://localhost:3000/users/authenticate',user,
{headers: headers})
.pipe(map(res => res.json));
}
}
login.component.ts
import { Component, OnInit } from '#angular/core';
import { AuthService } from '../../services/auth.service';
import { Router } from '#angular/router';
import { FlashMessagesService } from 'angular2-flash-messages';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
username: String;
password: String;
constructor(private authService: AuthService,
private router: Router,
private flashMessage: FlashMessagesService
) { }
ngOnInit() {
}
onLoginSubmit(){
const user = {
username: this.username,
password: this.password
}
this.authService.authenticateUser(user).subscribe(data => {
console.log(data);
});
}
}
Chrome Console
ƒ () { login.component.ts:29
if (typeof this._body === 'string') {
return JSON.parse(this._body);
}
if (this._body instanceof ArrayBuffer) {
return JSON.parse(this.text());
Below is the response in Postman :
The error is in your pipe function.
pipe(map( res => res.json ))
You need to call res.json() inside your map. Convert it to
pipe(map( res => res.json() ))
However, converting the response to JSON is not required over Angular v5.
Correct code is as below:-
authenticateUser(user){
let headers = new Headers();
headers.append('Content-Type','application/json');
return this.http.post('http://localhost:3000/users/authenticate',user,
{headers: headers})
.pipe(map(res => res.json()));
}
Looks like data coming from authenticateUser is a function. Have you tried calling it?

Angular 5 - Cannot use response from GET request

I've been at this and looking for a solution for two days now. Hoping someone can help me. I'm new to Angular 5.
I'm trying to utilize the WP REST API for a front page application. After following this tutorial:
http://techattitude.com/tips-tricks-and-hacks/how-to-remotely-create-a-user-on-your-wordpress-website-using-json-api-request/
I found that the there is a response that comes through, but I cannot access the response. I'm trying to console.log() the response value and nothing is appearing. Here is my code below, please have a look and let me know what I'm doing wrong. I have implemented my GET request through a service.
api-config-nonce.ts
export interface ApiConfigNonce {
status: String,
controller: String,
method: String,
nonce: String
}
auth.service.ts
import { EventEmitter, Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { ModalService } from '../services/modal.service';
import { Observable } from 'rxjs/Observable';
import { map } from 'rxjs/operators';
import { ApiConfigNonce } from '../api-config-nonce';
#Injectable()
export class AuthService {
apiHost:string = 'http://localhost/';
apiBase:string = 'b0ffv3BH7K6h/';
email:string;
password:string;
userSignIn = new EventEmitter<object>();
constructor(private http:HttpClient, private modalService:
ModalService){
}
login(email, password){
console.log('login()');
let options = {
"insecure":"cool",
"email":email,
"password": password
}
return this.http.post(this.apiHost + this.apiBase +
'user/generate_auth_cookie/' , options);
}
getNonce(){
return this.http.get<ApiConfigNonce>(this.apiHost + this.apiBase +
'get_nonce/?controller=user&method=register')
.map(res => res);
}
newUser(username, email, password, firstname, lastname, nonce){
return this.http.get(this.apiHost + this.apiBase + 'user/register/?
username='+ username + '&email=' + email + '&nonce=' + nonce +
'&first_name=' + firstname + '&last_name=' + lastname);
}
}
sign-up.component.ts
import { Component, OnInit, AfterViewInit, ViewChild } from
'#angular/core';
import { FormsModule } from '#angular/forms';
import { NgForm } from '#angular/forms';
import { UsersService } from '../../services/users.service';
import { AuthService } from '../../services/auth.service';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'app-sign-up',
templateUrl: './sign-up.component.html',
styleUrls: ['./sign-up.component.scss']
})
export class SignUpComponent implements OnInit, AfterViewInit {
#ViewChild('f') signupForm: NgForm;
signUpDetails:object;
busyProcessing:boolean = false;
errorMessage:string = null;
token:string = null;
userId:number = null;
nonce:any;
constructor(private usersService: UsersService, private authService:
AuthService, private http:HttpClient) { }
ngOnInit() {
this.getNonce();
}
ngAfterViewInit(){
}
getNonce(){
console.log('getNonce()');
this.authService.getNonce()
.subscribe(
data => {
this.nonce = JSON.stringify(data);
console.log(data);
},
(error)=>{
this.onError(error);
console.log(error);
}
);
console.log(this.nonce);
}
onError(response){
switch (response.error.code) {
case 406:
this.errorMessage = "Either that email or username is already in
use";
break;
case 403:
this.errorMessage = "Failed to authorize, please try again later";
default:
this.errorMessage = "There was an error signing you up, please try
again";
break;
}
this.busyProcessing = false;
}
}
The function in my component that is utilizing my service is getNonce(). I'm not sure why when I test the endpoints on postman I can see the response but cannot assign that response to a variable to use it. It renders this error:
"Http failure response for (unknown url): 0 Unknown Error"
Any help would be very appreciated.

How to pass form data from angular to nodejs

I am new to Angular5. I need to pass user details from angular to nodejs.
app.component.ts:
import { Component } from '#angular/core';
import { FormBuilder, FormGroup, Validators, FormControl, FormArray } from
'#angular/forms';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(private http:Http) { }
onSubmit(registerForm) {
console.log(registerForm.value);
let url = 'http://localhost:8080/signup';
this.http.post(url, {registerForm(registerForm)}).subscribe(res =>
console.log(res.json()));
}
}
Now I need to pass those data to nodejs routes to proceed further.
Node js routing file:
module.exports = function(app, passport) {
app.post('/signup', passport.authenticate('local-signup', {
successRedirect : '/',
failureRedirect : '/',
failureFlash : true
}));
};
Now am getting the following error: Uncaught Error: Can't resolve all parameters for AppComponent: (?).
Call Your function from the component.html file it will trigger the function which will be in your component.ts file.
From this function call service which contains the function which will be requesting your node API
addData() {
this.adminService.addCountry(this.form.value).subscribe(
res => {
var response = res.json();
this.flashMessagesService.show(response.message, {
cssClass: "alert-success",
timeout: 2000
});
},
error => {
if (error.status == 401) {
localStorage.removeItem("currentUser");
this.router.navigate(["/"]);
} else {
this.flashMessagesService.show(error.json().error, {
cssClass: "alert-danger",
timeout: 2000
});
}
}
);
}
Create admin service to call your HTTP URL which is running on node
Service
addCountry(formData) {
console.log(formData);
var authToken = this.getAuthToken();
if (authToken != "") {
var headers = this.getHeaders();
headers.append("Authorization", authToken);
return this.http
.post(
`http://localhost:3000/addData`,
this.formData(formData),
{ headers: headers }
)
.map((response: Response) => {
return response;
});
}
}
You can use service in angular to send data to nodeJs. Please refer the tutorials of Angular from Codecraft. Please have a look at https://codecraft.tv/courses/angular/http/core-http-api/
For now you need to send some registration form data. So
1. import http module to AppModule
2. Refer to the documentation above
3. You can pass data to nodejs using a POST method of http
I think you should look on Observable.
https://angular.io/guide/observables
On logic you should create server with Observable request to your NodeJs (express) app. Then you can add to your component function with subscribe.
Some code:
Create authentication service
ng generate service authentication
Create user service for store user data (or you can only store it in other components)
ng generate service user
On authentication.service.ts create authenticate method
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import { UserService } from '../user/user.service';
import { Router } from '#angular/router';`
#Injectable()
export class AuthenticationService {
token: string;
constructor(private router: Router, private httpClient: HttpClient,
public userService: UserService) {
const currentUser = JSON.parse(localStorage.getItem('currentUser'));
this.token = currentUser && currentUser.token;
}
getToken(email: string, password: string): Observable<User> {
return this.httpClient.post<User>(apiRoutes.authentication,
{userEmail: email, userPassword: password});
}
authenticate(email: string, password: string) {
this.getToken(email, password).subscribe(response => {
if (response.userToken.length > 0) {
this.userService.user.userEmail = response.userEmail;
this.userService.user.userToken = response.userToken;
this.userService.user._id = response._id;
this.userService.user.isUserAuthenticated = true;
localStorage.setItem('currentUser', JSON.stringify({token: response.userToken}));
this.router.navigate(['/']);
// TODO: Need some error logic
} else {
return false;
}
});
}
Now you can add to your form in template
<form (ngSubmit)="this.authenticationService.authenticate(userEmail, password)">
...
</form>

Resources