How to make a PUT request to an Express application - mysql

I'm trying to create a web application using Angular and Node for study, but my PUT request isn't working even though my GET requests work. It seems like Node is ignoring the requests and I can't find why. In my app I try to edit the name of a user when clicking a button and I can see that the request works until it gets to the http client in users-service.service.ts.
users.component.html
<router-outlet></router-outlet>
<h3>Usuários</h3>
<table>
<tr><td>Nome</td></tr>
<tr *ngFor="let user of users"><td>{{user.first_name}}</td><td><button (click)="showUserInfo($event, user)">Editar</button></td></tr>
</table>
<br/><br/>
<div>
<label>First Name: </label><input type="text" value="{{user.first_name}}" (input)="user.first_name = $event.target.value">
<label>Last Name: </label><input type="text" value="{{user.last_name}}" (input)="user.last_name= $event.target.value">
<button (click)="updateUser()">Salvar</button>
</div>
<br/><br/>
<button (click)="loadAllUsers()">Reload</button>
users.component.ts
import { HttpClient, HttpClientModule } from '#angular/common/http';
import { UsersService, User } from './../users-service.service';
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-users',
providers: [UsersService, HttpClient, HttpClientModule],
templateUrl: './users.component.html',
styleUrls: ['./users.component.sass']
})
export class UsersComponent implements OnInit {
private users: User[];
private user: User = {first_name: '', last_name: '', id: null};
constructor(private service: UsersService) {
this.loadAllUsers();
}
ngOnInit() {}
showUserInfo(event, u : User) {
this.user = u;
}
loadAllUsers() {
this.service.getAllUsers().subscribe(valor => { this.users = valor as User[] });
}
updateUser() {
console.log(this.user);
this.service.updateUser(this.user);
}
}
users-service.service.ts
import { HttpClient, HttpClientModule, HttpHeaders } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs';
export interface User{
first_name: string,
last_name: string,
id: number
}
#Injectable()
export class UsersService{
constructor(private http: HttpClient) { }
getAllUsers(): Observable<User[]>{
return this.http.get<User[]>("http://localhost:4600/api/users");
}
updateUser(user: User): Observable<void>{
console.log('Updating: ' + user);
console.log("http://localhost:4600/api/users/" + user.id);
return this.http.put<void>("http://localhost:4600/api/users/" + user.id, user);
}
}
server.js
const express = require('express');
app = new express();
const morgan = require('morgan');
const cors = require('cors');
const mysql = require('mysql');
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(morgan('dev'));
app.use('*', cors());
app.listen(4600, () => {
console.log("Server listening on port 4600...");
});
//All users
app.get("/api/users", (req, res) => {
let connection = getConnection();
connection.query('SELECT * FROM USERS', (err, result) => {
if(err){
throw err;
}
console.log(result);
res.json(result);
});
});
//Specific user
app.get('/api/users/:id', (req, res) => {
getConnection().query('SELECT * FROM USERS WHERE ID = ?', req.params.id, (err, result) => {
if(err){
console.log(err.message);
throw err;
}
res.json(result);
});
});
//Update user
app.put("/api/users/:id", (req, res) => {
console.log('PUT request received...');
getConnection().query("UPDATE USERS SET FIRST_NAME = ?, LAST_NAME = ? WHERE ID = ?", [req.body.first_name, req.body.last_name, req.body.id], (err, result) => {
if(err){
console.log(err.message);
throw err;
}
res.send(201, req.body);
});
});
//Delete user
app.delete('/api/users/:id', (req, res) => {
});
function getConnection(){
return mysql.createConnection({
host: 'localhost',
user: '',
password: '',
database: 'test'
});
}
EDIT 1
Based on #tadman comment I searched for the Network tools available in my browser and I found out, as expected, that the POST request were being ignored. By subscribing to the http client, the POST requests started to be noticed as they should. The answer by #KeaganFouche in the question bellow helped me:
Angular 4.0 http put request
New update method in the Angular service:
updateUser(user: User): void{
console.log('Updating: ' + user);
console.log("http://localhost:4600/api/users/" + user.id);
this.http.put<void>("http://localhost:4600/api/users/" + user.id, user).subscribe((response) => {console.log(response)});
}

Based on #tadman comment I searched for the Network tools available in my browser and I found out, as expected, that the POST request were being ignored. By subscribing to the http client, the POST requests started to be noticed as they should. The answer by #KeaganFouche in the question bellow helped me: Angular 4.0 http put request
New update method in the Angular service:
updateUser(user: User): void{
console.log('Updating: ' + user);
console.log("http://localhost:4600/api/users/" + user.id);
this.http.put<void>("http://localhost:4600/api/users/" + user.id, user).subscribe((response) => {console.log(response)});
}

Related

How to interface JSON data and display table

So I am trying to display a list of devices from the database into an angular material table. I've written the REST api for it which is something like this:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const mysql = require('mysql');
//parse application/json
app.use(bodyParser.json());
//create database connection
const conn = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'project'
});
//connect to database
conn.connect((err) =>{
if(err) throw err;
console.log('Mysql connected....');
});
//server listening
app.listen(3000,() =>{
console.log('Server started on port 3000');
});
//show login page
app.use(express.static(__dirname+'/dashboard'))
app.get('/',(req,res) => {
res.send('Use /api/devices');
});
//show all devices
app.get('/api/devices',(req,res) => {
let sql = "SELECT * FROM tempstatus";
let query = conn.query(sql, (err, results) => {
if(err) throw err;
res.send(JSON.stringify({'status': 200, 'error': null, 'response': results}));
});
});
And now I have written a controller as follows:
var myApp = angular.module('myApp', [require('angular-material-data-table')]);
myApp.controller('DeviceController', function($scope, $http){
console.log('DeviceController loaded')
$scope.getDevices = function(){
var device = null;
$http.get('/api/devices').success(function(response) {
device = response;
});
}
}
I'm rather new to Angular and nodejs and I don't really know how what else I must do and how to display the data I get in an angular material table. Can you please help me out?
This is the JSON data I'm getting from the API:
"status":200,"error":null,"response": {"serialnum":"0","time":"2020-02-11T12:36:27.000Z","type":"","temparature":"","date":"2020-02-10T18:30:00.000Z","status":"not active","comments":""}
And this is the angular.module.ts file. As I said, I'm new to angular and I don't know how to write my code. So far I've only done this and the controller in angular:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpClientModule } from '#angular/common/http';
#NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

how to solve problems: zone.js:3243 POST http://localhost:4200/login 404 (Not Found)

I want to do a simple login function for my page.I use Angular-MySQL-Express-Sequelize for this page.
When I do a POST to login, it always tell me
zone.js:3243 POST http://localhost:4200/login 404 (Not Found)
I don't know what is that means and how to solve it.
This is my customer.service.ts
export interface Details {
username: string;
password: string;
age: number;
type: string;
}
interface TokenResponse {
token: string;
}
export interface TokenPayLoad {
username: string;
password: string;
}
public login(customer: TokenPayLoad): Observable<any> {
const base = this.http.post('/login', customer);
const request = base.pipe(
map((data: TokenResponse) => {
if (data.token) {
this.saveToken(data.token);
}
return data;
})
);
return request;
}
////
This is my login.component.ts
credentials: TokenPayLoad = {
username: '',
password: '',
};
constructor(private customerService: CustomerService, private router: Router){}
ngOnInit() {
}
login() {
this.customerService.login(this.credentials).subscribe (
() => {
this.router.navigateByUrl('/customer');
},
err => {
}
);
}
////
This is my backend login function
exports.login = (req, res) =>{
Customer.findOne(
{where: {
username: req.body.username,
password: req.body.password
}
}).then(customer => {
if(req.body.password = customer.password){
let token = jwt.sign(customer.dataValues, secret_key, {
expiresIn: 1400
})
res.json({token: token});
}
else{
res.send('user not exists');
}
})
.catch(err => {
res.send('error is ' + err);
})
}
Assuming that you are using Angular-CLI to create your project. You will need to proxy your API (if you want to use the same port ie 4200).
The article below shows you how to configure proxy with Angular CLI
https://itnext.io/angular-cli-proxy-configuration-4311acec9d6f

Angular sending a request to node api

In my angular app, I send a post request to node API with JSON data object, but it doesn't work as intended. In the request payload, the JSON data object is not shown.
When i send a JSON string by using JSON.stringify(auth) it's shown in the request payload but can't be parsed by the json body-parser at the node backend. Requests body is empty. Give me a solution to this problem.
My code
import { Injectable } from "#angular/core";
import { AuthData } from "../modules/AuthData";
import {
HttpClient,
HttpParams,
HTTP_INTERCEPTORS,
HttpInterceptor,
HttpHeaders
} from "#angular/common/http";
#Injectable({
providedIn: "root"
})
export class AuthService {
private url = "http://localhost:3000";
private httpOptions = {
headers: new HttpHeaders({
"Content-Type": "application/json",
Authorization: "my-auth-token",
"Request-Method": "post"
})
};
constructor(private http: HttpClient) {}
login(email: string, password: string) {
const authData = { email: email, password: password };
console.log(authData);
this.http
.post(this.url + "/api/user/login", authData)
.subscribe(response => {
console.log(response);
});
}
}
My backend code
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const mongoose = require("mongoose");
const cors = require('cors');
const userRoute = require("./routes/user");
const app = express();
mongoose
.connect('mongodb://localhost:27017/tryondb', {
useNewUrlParser: true
})
.then(() => {
console.log("connected to the database");
})
.catch(() => {
console.log("connection failed");
})
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:false}));
//var jsonParser = bodyParser.json();
//var urlencodedParser = bodyParser.urlencoded({ extended: false });
//app.use(cors);
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Header",
"Origin, X-Requested-with, Content-Type, Accept"
);
res.setHeader(
"Access-Control-Allow-Methods",
"GET, POST, PATCH, DELETE, OPTIONS"
);
console.log("rrr");
next();
})
app.post("/api/user/login",(req,res,next)=>{
console.log(req);
});
app.use("/api/user", userRoute);
console.log("aaa");
module.exports = app;
you are creating httpoptions but you are not passing them correctly: try
login(email: string, password: string) {
const authData = { email: email, password: password };
console.log(authData);
this.http
.post(this.url + "/api/user/login", authData, httpOptions)
.subscribe(response => {
console.log(response);
});
}

Can't get data form nodejs by angular

Hi I can't get data from nodejs by angular 6.
I added a service to connect between them but it is not working.
I succeed to get data by nodejs server, but I can't receive it on angular components.
I know that I missed something to connect between them but I can't resolve it.
HostingstartComponent.ts
import { Component, OnInit } from '#angular/core';
import { NgAnalyzedFile } from '#angular/compiler';
import {RouterModule ,Routes } from '#angular/router';
import {HttpModule, Http} from '#angular/http'
import { AngularFontAwesomeModule } from 'angular-font-awesome';
import { SecComponent } from '../sec/sec.component';
import { ThirdComponent } from '../third/third.component';
import {aService} from '../services/a.service';
#Component({
selector: 'app-hostingstart',
templateUrl: './hostingstart.component.html',
styleUrls: ['./hostingstart.component.css']
})
export class HostingstartComponent implements OnInit {
aService: any;
data: any;
appRoutes : Routes=[
{path: 'hostingstar',component : HostingstartComponent},
{path: '',component : HostingstartComponent},
{path: 'sec',component : SecComponent, data : {some_data : 'some value'}},
{path: 'third',component : ThirdComponent, data : {some_data : 'some value'}}
];
headImg : any="assets/images/pan.JPG";
constructor(private http: Http , private service: aService) {
this.headImg ="assets/images/pan.JPG";
// this.aService.getData().then( (result) => {this.data = result; });
}
ngOnInit() {
// alert(this.aService.getData());
// this.aService.getData().then( (result) => {this.data = result; });
// alert(this.data);
}
myFunc() {
//this.router.navigate(['/third', 'north']);
// alert( document.getElementById("search-input").value);
}
getData() {
this.aService.getData().subscribe((dataFromServer) => {
this.data=dataFromServer;
// Now you can use the data
// alert(dataFromServer)
console.log(dataFromServer);
});
}
}
aService.ts
import 'rxjs/add/operator/toPromise';
import { Http, Response, Headers } from '#angular/http';
import { Injectable } from '#angular/core';
#Injectable()
export class aService {
constructor(private http: Http) {
}
async getData() {
const options = {
headers: new Headers({
'Content-Type': 'application/json;charset=utf-8',
'Access-Control-Allow-Origin': '*'
})
};
// const url = './assets/heroes.data.json';
const url = 'http://localhost:3000/';
return this.http.get(url, options)
.toPromise()
.then(response => {
if (response != null) {
const result = response.json();
return Promise.resolve(result);
}
return [];
})
.catch(err => {
console.warn('error in getCats', err);
return Promise.reject(null);
});
}
}
Node js : index.js
console.log('Running File: index.js')
//-- Create Express Server:
var express = require('express');
var app = express();
var util = require('util');
var mysql = require('mysql');
var a;
var con = mysql.createConnection({
host : 'localhost',
user: 'node',
password : 'arafat1990!##$',
database: "iTour"
});
con.connect(function(err) {
if (err) throw err;
con.query("SELECT * FROM feedback", function (err, result, fields) {
if (err) throw err;
// console.log(result);
a=result;
});
});
//-- Map Base URL to res (Response)
app.get('/', function(req, res){
var fname = req.query.fname;
var lname = req.query.lname;
var html = util.format('<p>Hello %s %s</p>', a[1].username,a[0].rating);
res.send(a);
});
app.get('/hostingstar', function(req, res){
var fname = req.query.fname;
var lname = req.query.lname;
var html = util.format('<p>Hello %s %s</p>', a[1].username,a[0].rating);
res.send(a);
});
//-- Listen on Port 3000:
app.listen(3000);
app.js
const express = require('express');
const app = express();
//const firebase = require('firebase-admin');
app.get('/hostingstart', (req, res) => res.send('Server Is Active!'))
app.get('/hostingstart', (req, res) => {
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user: 'node',
password : 'arafat1990!##$',
database: "iTour"
});
connection.connect();
connection.query('SELECT * FROM feedback;', function (error, results, fields) {
if (error) {
console.warn(error);
res.send('');
return;
}
console.log("Result: " + results);
res.send(results);
});
connection.end();
})
app.get('/hostingstart', (req, res) => {
var ref = firebase.app().database().ref();
ref.once("value").then(function (snap) {
console.log("snap.val()", snap.val());
res.send(snap.val());
});
});
app.use(function(req, res, next){
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Credentials", "true");
res.setHeader("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
res.setHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
// Check if preflight request
if (req.method === 'OPTIONS') {
res.status(200);
res.end();
}
else {
next();
}
});
app.listen(3000, () => console.log('Server is listening on port 3000!'))
In your getService method you are calling the service itself not the property from the constructor.
Your:
this.aService.getData()
Should be:
this.service.getData()
Additionally call myFunc() in ngOnInit
ngOnInit() {
this.myFunc()
}

how to pass data from save function to server in MySQL using API call

I am new to Angular 2&4, when I am trying to connect angular4 with MySQL using HTTP.post method. The values are not passing to API/save in server.js. Can anyone please help how to insert data into MySQL from angular4.
I am getting an error at server.js.
app.component.html
<main class="content">
<h2>Login</h2>
<form>
<div class="form-group">
<label for="username">UserName: </label>
<input type="text" name="username" [(ngModel)]="person.username" class="form-control" required />
</div>
<div class="form-group">
<label for="password">Password: </label>
<input type="text" name="password" [(ngModel)]="person.password" class="form-control" required />
</div>
<div class="form-group">
<button class="btn btn-primary" (click)="save()" >Save</button>
</div>
</form>
</main>
app.component.js
import { Component, OnInit } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { ActivatedRoute} from '#angular/router';
import { Location } from '#angular/common';
import { Http, Headers, RequestOptions } from '#angular/http';
import 'rxjs/add/operator/map';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
public person: any;
public constructor(private http: Http, private route: ActivatedRoute, private location: Location) {
this.person = {
"username": "",
"password": ""
};
}
public ngOnInit() {}
public save() {
console.log("save function starts");
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
console.log("save function middle"+ JSON.stringify(this.person));
this.http.post("http://localhost:3000/api/save", JSON.stringify(this.person), options)
.map(result => result.json())
.subscribe(results => {
this.location.back();
}, error => {
console.error(error);
});
}
}
server.js
var app = express();
var path = require("path");
var postsModel = require('./models/posts');
var bodyParser = require('body-parser');
var mysql = require('mysql2');
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'admin',
database: 'Speckle'
});
var app = express();
connection.connect(function(err){
if(!err) {
console.log("Database is connected ... nn");
} else {
console.log("Error connecting database ... nn");
}
});
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
app.post("/api/save",function(req, res) {
console.log("request"+ req.body.username);
postsModel.save(req.body);
});
app.use(express.static(path.join(__dirname, "")));
app.listen(3000);
posts.js
var database = require('./database');
exports.save = function (params) {
return database.query("INSERT INTO login SET ?", params)
.then(function (result) {
console.log("save");
return result.insertusername;
});
};
database.js
var mysql = require('mysql2');
var connection;
exports.init = function (config) {
connection = mysql.createConnection(config);
};
exports.query = function (sql, params) {
return new Promise(function (resolve, reject) {
console.log("SQL statement" + sql);
console.log("sql"+sql +""+"params" +params.username+params.password);
connection.query(sql, params, function(error, result) {
if (error) {
return reject(error);
}
resolve(result);
});
});
};
instead of this
<button class="btn btn-primary" (click)="save()" >Save</button>
you can go with this.
<button class="btn btn-primary" (click)="save(person)" >Save</button>
public save(person) {
console.log("save function starts");
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
console.log("save function middle"+ JSON.stringify(this.person));
this.http.post("http://localhost:3000/api/save", JSON.stringify(person), options)
.map(result => result.json())
.subscribe(results => {
this.location.back();
}, error => {
console.error(error);
});
}
The problem here is that you are performing stringify JSON data and at the server side you doesn't parse it to the JSON. However at requests you don't have to stringify it becasuse you can just sent JSON data without any errors. But If you want to send stringified JSON you have to parse it to JSON to use it as param.login or param.password, without this you are just refering to the string to non-existing property. So after you send data you should perform on data JSON.parse().
try this
public save() {
console.log("save function starts");
let data = this.person;
this.http.post("http://localhost:3000/api/save",data)
.map(result => result.json())
.subscribe(results => {
this.location.back();
}, error => {
console.error(error);
});
}