How to get data back in frontend from database after posting - node.js

import { Component, OnInit, Input } from '#angular/core';
import { Router } from '#angular/router';
import { FormBuilder, FormGroup, FormArray } from '#angular/forms';
import { Validators } from '#angular/forms';
import { HttpService } from '../http.service';
#Component({
selector: 'todo-app',
templateUrl: './todo-app.component.html',
styleUrls: ['./todo-app.component.css']
})
export class TodoAppComponent implements OnInit {
myForm: FormGroup;
todoitems = [];
todolist;
submitted = false;
name;
constructor(private router: Router, private formBuilder: FormBuilder, private httpService: HttpService ) {
}
ngOnInit() {
this.myForm = this.formBuilder.group({
todoitems : [this.todolist, Validators.compose([Validators.required, Validators.minLength(3)])]
});
this.httpService.gettodo().subscribe(
(data:any[]) => {
this.todoitems = data;
console.log(this.name);
}
);
}
addTodo() {
if (this.myForm.invalid) {
this.submitted = true;
}
if (this.myForm.valid) {
var body = { name: this.todolist }
this.httpService.addTodoo(body).subscribe(
(data:any) => {
this.todoitems = data;
}
)
this.myForm.reset();
this.submitted = false;
}
}
deletetodo(id: any) {
console.log(id);
this.httpService.deleteTodo(id).subscribe((data)=>{
this.todoitems = data;
});
}
}
<form [formGroup]="myForm">
<div>
<input formControlName="todoitems" [(ngModel)]="todolist" name="todoitems">
<button type="submit" (click)="addTodo()">Add</button>
<div>
<div *ngIf="submitted && myForm.controls.todoitems.errors">
<div *ngIf="myForm.controls.todoitems.errors.required"> please fill</div>
<div *ngIf="myForm.controls.todoitems.errors.minlength">min 3</div>
</div>
</div>
</div>
<br>
<div>
<table style="width:50%">
<tr *ngFor="let todoitem of todoitems; let i = index" >
<td>{{ todoitem.name }}</td>
<td>
<button (click)="deletetodo(todoitem.id)">Delete</button>
</td>
</tr>
</table>
</div>
</form>
i'm posting my data from frontend and its going to the backend just
fine, but it is not showing on the front end, how do i get data back
correctly and print in frontend
app.post('/api/names', (req, res) => {
let todoitem = {todoitems:req.body.name
};
var sql = `INSERT INTO todolist SET?`;
mysqlConnection.query(sql, todoitem, (err) => {
if (err) throw err;
res.send(200)
})
});
app.get('/api/names', (req, res) => {
mysqlConnection.query('SELECT todoitems FROM todolist', (err, rows, fields) => {
if (!err)
res.send(rows);
else
console.log(err);
})
});

app.get('/api/names', (req, res) => {
var query = 'select id, code, name from Continent'
findTodoItems(query, function(err, results) {
if (err) {
console.log(err)
throw err;
}
res.send(results);
});
});
function findTodoItems(queryString, cb) {
mysqlConnection.query(queryString, function (err, rows, fields) {
cb(err, rows);
});
};

Related

edit by id is not working in Angular although the route that is getting passed is correct

I want to edit and show value in form when user is editing but its not working. Angular frontend is capturing the correct route but data is not getting fetched from backend and no api is getting called. The content is not shown on browser. I'm attatching the git repository link also in case if you want to take a look https://github.com/tridibc2/blog-admin-mean. The route to do the editing is http://localhost:4200/admin/blog and click on edit button. Below I'm attaching edit-blog.component.html code
<h3>Edit this blog</h3>
<div class="row" style="text-align:left">
<div class="col-md-12">
<form #createBlogForm="ngForm" (ngSubmit)="editThisBlog()">
<div class="form-group">
<label>Blog Title</label>
<input type="text" name="blogTitle" [(ngModel)]="currentBlog.title" #title="ngModel" class="form-control" placeholder="Enter blog Title"
required>
</div>
<div [hidden]="title.valid || title.pristine" class="alert alert-danger">
Blog Title is required
</div>
<div class="form-group">
<label>Description</label>
<input type="text" name="blogDescription" [(ngModel)]="currentBlog.description" #description="ngModel" class="form-control" placeholder="Enter Description"
required>
</div>
<div class="form-group">
<label>Enter the blog body</label>
<textarea name="blogBodyHtml" [(ngModel)]="currentBlog.bodyHtml" #bodyHtml="ngModel" class="form-control" rows="3" required></textarea>
</div>
<div class="form-group">
<label>Category</label>
<select [(ngModel)]="currentBlog.category" #category="ngModel" name="blogCategory" class="form-control" id="category" required>
<option *ngFor="let category of possibleCategories" [value]="category">{{category}}</option>
</select>
</div>
<button type="submit" class="btn btn-default" [disabled]="!createBlogForm.form.valid">Edit the blog</button>
</form>
</div>
</div>
</div>
edit-blog.component.ts
import { ActivatedRoute, Router } from '#angular/router';
import { BlogpostService } from 'src/app/client/blogpost.service';
import { ToastsManager } from 'ng6-toastr/ng2-toastr';
import { FormGroup, FormBuilder } from '#angular/forms';
#Component({
selector: 'app-edit-blog',
templateUrl: './edit-blog.component.html',
styleUrls: ['./edit-blog.component.css']
})
export class EditBlogComponent implements OnInit {
public currentBlog;
public possibleCategories = ["Comedy", "Action", "Drama", "Technology","Cooking","Travel"];
constructor(private blogpostService: BlogpostService, private _route: ActivatedRoute, private router: Router, public toastr: ToastsManager) { }
ngOnInit() {
console.log("blogedit ngOnInIt called");
let myBlogId = this._route.snapshot.paramMap.get('blogId');
console.log(myBlogId);
this.blogpostService.getSingleBlogInformation(myBlogId).subscribe(
data =>{
console.log(data);
this.currentBlog = data;
console.log(this.currentBlog);
},
error =>{
console.log("some error occured");
console.log(error.errorMessage);
})
}
public editThisBlog(): any {
this.blogpostService.editBlog(this.currentBlog.blogId, this.currentBlog).subscribe(
data =>{
console.log(data);
this.toastr.success('Blog Edited Successfully.', 'Success!');
setTimeout(() =>{
this.router.navigate(['/blog', this.currentBlog.blogId]);
}, 1000)
},
error =>{
console.log(error);
console.log(error.errorMessage);
this.toastr.error('Some Error Occured.', 'Oops!');
}
)
}
}
service code
import { catchError } from 'rxjs/operators';
import { HttpClient, HttpErrorResponse, HttpBackend, HttpParams } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import { throwError } from 'rxjs';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
#Injectable({
providedIn: 'root'
})
export class BlogpostService {
public allBlogs;
public currentBlog;
errorData: {};
isLoggedIn = false;
public baseUrl = 'http://localhost:4000/api/v1/blogs';
constructor(private _http:HttpClient, private handler: HttpBackend) { }
public getAllBlogs(): any {
let myResponse = this._http.get(this.baseUrl + '/all').pipe(
catchError(this.handleError)
);
console.log(myResponse);
return myResponse;
}
public getSingleBlogInformation(currentBlogId): any {
let myResponse = this._http.get(this.baseUrl + '/view/' + currentBlogId).pipe(
catchError(this.handleError)
);
return myResponse;
}
public createBlog(blogData): any {
let myResponse = this._http.post(this.baseUrl + '/create', blogData);
return myResponse;
}
public deleteBlog(blogId): any {
let data = {}
let myResponse = this._http.post(this.baseUrl + '/' + blogId + '/delete', blogId);
return myResponse;
}
public editBlog(blogId, blogData): any {
let myResponse = this._http.put(this.baseUrl + '/edit' + '/' + blogId, blogData);
return myResponse;
}
public getUserInfoFromLocalStorage: any = () =>{
return JSON.parse(localStorage.getItem('userInfo'));
}
public setUserInfoInLocalStorage: any = (data) =>{
localStorage.setItem('userInfo', JSON.stringify(data))
}
public signinFunction(data): Observable<any>{
const params = new HttpParams()
.set('email', data.email)
.set('password', data.password)
return this._http.post(`${this.baseUrl}/login`, params);
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(`Backend returned code ${error.status}, ` + `body was: ${error.error}`);
}
// return an observable with a user-facing error message
this.errorData = {
errorTitle: 'Oops! Request for document failed',
errorDesc: 'Something bad happened. Please try again later.'
};
return throwError(this.errorData);
}
}
node controller code for the edit api
BlogModel.findOne({ 'blogId': req.params.blogId }, (err, result) => {
if (err) {
console.log(err)
res.send(err)
} else if (result == undefined || result == null || result == '') {
console.log('No Blog Found')
res.send("No Blog Found")
} else {
result.views += 1;
result.save(function (err, result) {
if (err) {
console.log(err)
res.send(err)
}
else {
console.log("Blog updated successfully")
res.send(result)
}
});// end result
}
});
}
route
app.put(baseUrl+'/edit/:blogId',blogController.editBlog);
the data object is like this
{"title":"Blog Title 2 Custom","description":"Blog description 2 Custom","bodyHtml":"<h3>Heading of the body CUSTOM</h3><p>This is the first blog data getting uploaded n blog project</p>","views":5,"isPublished":true,"category":"tech","author":"Decardo","tags":["english movies, action movies, comedy"],"_id":"5e1120d223416207d8ae5e1b","blogId":"nbfO8hJp","created":"2020-01-04T23:33:38.000Z","lastModified":"2020-01-04T23:33:38.000Z","__v":0}
Just fix the path of edit button like this:
<a [routerLink]="['/admin/edit', blog.blogId]" class="btn btn-info btn-sm">Edit</a>
Forward on the API part your edit method is incomplete as you are not updating the object that you find with the new values.
let editBlog = (req, res) => {
const data = req.body;
BlogModel.findOne({ 'blogId': req.params.blogId }, (err, result) => {
if (err) {
console.log(err)
res.send(err)
} else if (result == undefined || result == null || result == '') {
console.log('No Blog Found')
res.send("No Blog Found")
} else {
for (let key in data) {
result[key] = data[key];
}
result.views += 1;
result.save(function (err, result) {
if (err) {
console.log(err)
res.send(err)
}
else {
console.log("Blog updated successfully")
res.send(result)
}
});// end result
}
});
};
To edit the Blog's info you are calling editBlog method from blogpost service passing into it an id (blogId) and a body (blogData). So on the server side what you get is an id and body which is the update data. You can get the body from request so req.body. What you missed is to update actually the object you found, and that's why i made a loop to update the values of Blog object with the new values from req.body, and only once updated you save it. Obviously there are other ways to update the object we want to modify.

Angular get blog by id not displaying anything on browser

I'm building a blog application based on MEAN stack, using Angular in front-end, node in back-end and mongoDB for server. When I'm trying to access a particular blog by it's blogId, the browser is not showing anything. Although I'm getting the right data fetched from backend with a 304 status and the right blogId is also passing by the route. The console is also logging the right object. Below is my blog-view.component.ts file
import { ActivatedRoute, Router } from '#angular/router';
import { ToastrManager } from 'ng6-toastr-notifications';
import { BlogService } from '../blog.service';
import { BlogHttpService } from '../blog-http.service';
import { Location } from '#angular/common';
#Component({
selector: 'app-blog-view',
templateUrl: './blog-view.component.html',
styleUrls: ['./blog-view.component.css'],
providers: [Location]
})
export class BlogViewComponent implements OnInit, OnDestroy {
public currentBlog;
constructor(private _route: ActivatedRoute, private router: Router, public blogHttpService:BlogHttpService, public toastr: ToastrManager, private location: Location) {
console.log("view-blog constructor called")
}
ngOnInit() {
console.log("view-blog ngOnInIt called");
let myBlogId = this._route.snapshot.paramMap.get('blogId');
console.log(myBlogId);
this.currentBlog = this.blogHttpService.getSingleBlogInformation(myBlogId).subscribe(
data =>{
console.log(data);
this.currentBlog = data["data"];
},
error =>{
console.log("some error occured");
console.log(error.errorMessage);
})
}
public deleteThisBlog(): any {
this.blogHttpService.deleteBlog(this.currentBlog.blogId).subscribe(
data =>{
console.log(data);
this.toastr.successToastr('This blog is successfully deleted.', 'Success!');
setTimeout(() =>{
this.router.navigate(['/home']);
}, 1000)
},
error =>{
console.log(error);
console.log(error.errorMessage);
this.toastr.errorToastr('Some Error Occured.', 'Oops!');
}
)
}
public goBackToPreviousPage(): any {
this.location.back();
}
ngOnDestroy(){
console.log("view-blog component destroyed");
}
}
blog-view.component.html
<div class="row" *ngIf="currentBlog" style="text-align: center;">
<div class="col-md-12">
<h2>{{currentBlog.title}}</h2>
<p>posted by {{currentBlog.author}} on {{currentBlog.created | date:'medium'}}</p>
<p *ngIf="currentBlog.tags!=undefined && currentBlog.tags.length>0">tags : <span *ngFor="let tag of currentBlog.tags;let first=first;let last=last">{{tag}}{{last ? '' : ', '}}</span></p>
<hr>
<div [innerHtml]="currentBlog.bodyHtml"></div>
<hr>
<h5>category - {{currentBlog.category}}</h5>
</div>
<hr>
<div class="row" *ngIf="currentBlog">
<div class="col-md-4">
<a class="btn btn-primary" [routerLink]="['/edit',currentBlog.blogId]">Edit</a>
</div>
<div class="col-md-4">
<a class="btn btn-danger" (click)="deleteThisBlog()">Delete</a>
</div>
<div class="col-md-4">
<a class="btn btn-warning" (click)="goBackToPreviousPage()">Go Back</a>
</div>
</div>
</div>
</div>
blog-http.service.ts
import { HttpClient, HttpErrorResponse } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';
#Injectable()
export class BlogHttpService {
public allBlogs;
public currentBlog;
public baseUrl = 'http://localhost:3000/api/v1/blogs';
constructor(private _http:HttpClient) {
console.log('blog http service constructor called');
}
private handleError(err:HttpErrorResponse){
console.log("handle error http calls");
console.log(err.message);
return Observable.throw(err.message)
}
public getAllBlogs(): any {
let myResponse = this._http.get(this.baseUrl + '/all');
console.log(myResponse);
return myResponse;
}
public getSingleBlogInformation(currentBlogId): any {
let myResponse = this._http.get(this.baseUrl + '/view/' + currentBlogId);
return myResponse;
}
public createBlog(blogData): any {
let myResponse = this._http.post(this.baseUrl + '/create', blogData);
return myResponse;
}
public deleteBlog(blogId): any {
let data = {}
let myResponse = this._http.post(this.baseUrl + '/' + blogId + '/delete', blogId);
return myResponse;
}
public editBlog(blogId, blogData): any {
let myResponse = this._http.put(this.baseUrl + '/' + blogId + '/edit' , blogData);
return myResponse;
}
}
my nodejs routes with controller for blog-view
app.get(baseUrl+'/view/:blogId', (req, res) => {
BlogModel.findOne({ 'blogId': req.params.blogId }, (err, result) => {
if (err) {
console.log(err)
res.send(err)
} else if (result == undefined || result == null || result == '') {
console.log('No Blog Found')
res.send("No Blog Found")
} else {
res.send(result)
}
})
});
Below is a sample document object from which the frontend should render
{
"_id": "5e0e8ac6dcfc4e2008390cdf",
"blogId": "XAY2Qlhb",
"__v": 0,
"lastModified": "2020-01-03T00:28:54.638Z",
"created": "2020-01-03T00:28:54.638Z",
"tags": [
"english movies, action movies"
],
"author": "Decardo",
"category": "Hollywood custom",
"isPublished": true,
"views": 8,
"bodyHtml": "<h1>Heading of the body</h1>\n<p>This is the first blog data getting uploaded n blog project</p>",
"description": "long description>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>",
"title": "Blog Title 1 custom"
}
This line of code will first store a Subscription in this.currentBlog:
this.currentBlog = this.blogHttpService.getSingleBlogInformation(myBlogId).subscribe(...)
Then the subscription will be overwritten by this.currentBlog = data["data"];
this.currentBlog = is actually not needed there.
Not sure if that is the problem. At least it is not proper :)

How to fix "Can't perform a React state update on an unmounted component"?

I'm building a TODO list and one of the things that it needs to do is delete.
Here is my server.js code
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
const cpdRoutes = express.Router();
const PORT = 4000;
let Cpd = require("./cpd.model");
app.use(cors());
app.use(bodyParser.json());
//connects my backend to my mongo database
mongoose.connect('mongodb://127.0.0.1:27017/cpds', { useNewUrlParser: true });
const connection = mongoose.connection;
connection.once('open', function() {
console.log("MongoDB database connection established successfully");
})
cpdRoutes.route('/').get(function(req, res) {
Cpd.find(function(err, cpds) {
if (err) {
console.log(err);
}
else {
res.json(cpds);
}
});
});
//finds the data by id
cpdRoutes.route('/:id').get(function(req, res) {
let id = req.params.id;
Cpd.findById(id, function(err, cpd) {
res.json(cpd);
});
});
//creating data
cpdRoutes.route('/add').post(function(req, res) {
let cpd = new Cpd(req.body);
cpd.save()
.then(cpd => {
res.status(200).json({'cpd': 'New data added successfully'});
})
.catch(err => {
res.status(400).send('Adding new data failed');
});
});
//update data
cpdRoutes.route('/update/:id').post(function(req, res) {
Cpd.findById(req.params.id, function(err, cpd) {
if (!cpd)
res.status(404).send("data is not found");
else
cpd.cpd_date = req.body.cpd_date;
cpd.cpd_activity = req.body.cpd_activity;
cpd.cpd_hours = req.body.cpd_hours;
cpd.cpd_learningStatement = req.body.cpd_learningStatement;
cpd.save().then(cpd => {
res.json('Data updated!');
})
.catch(err => {
res.status(400).send("Update not possible");
});
});
});
// cpdRoutes.route('/delete/:id').post(function(req, res) {
// Cpd.findById(req.params.id, function(err, cpd) {
// if (!cpd)
// res.status(404).send("data is not found");
// else
// cpd.cpd_date = req.body.cpd_date;
// cpd.cpd_activity = req.body.cpd_activity;
// cpd.cpd_hours = req.body.cpd_hours;
// cpd.cpd_learningStatement = req.body.cpd_learningStatement;
// cpd.save().then(cpd => {
// res.json('Data updated!');
// })
// .catch(err => {
// res.status(400).send("Update not possible");
// });
// });
// });
cpdRoutes.route.get('/delete', function(req, res){
var id = req.query.id;
Cpd.find({_id: id}).remove().exec(function(err, expense) {
if(err)
res.send(err)
res.send('Data successfully deleted!');
})
});
app.use('/cpds', cpdRoutes);
app.listen(PORT, function() {
console.log("Server is running on Port: " + PORT);
});
My delete component:
import React from 'react';
import axios from 'axios';
import { Button } from 'react-bootstrap';
import { Link } from 'react-router-dom';
class DeleteCpd extends React.Component {
constructor(){
super();
this.state={id:''};
this.onClick = this.onClick.bind(this);
this.delete = this.delete.bind(this);
}
// componentDidMount() {
// this.setState({
// id: this.props.cpds.id
// })
// }
componentDidMount() {
axios.get('http://localhost:4000/cpds/'+this.props.match.params.id)
.then(response => {
this.setState({
cpd_date: response.data.cpd_date,
cpd_activity: response.data.cpd_activity,
cpd_hours: response.data.cpd_hours,
cpd_learningStatement: response.data.cpd_learningStatement
})
})
.catch(function (error) {
console.log(error);
})
}
onClick(e){
this.delete(this);
}
delete(e){
axios.get('http://localhost:4000/cpds/'+this.props.match.params.id)
.then(function(response) {
});
}
render(){
return (
<Button onClick={this.onClick}>
<Link to={{pathname: '/', search: '' }} style={{ textDecoration: 'none' }}>
<span className="glyphicon glyphicon-remove"></span>
</Link>
</Button>
)
}
}
export default DeleteCpd;
and my App.js:
import React, { Component } from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import CreateCpd from "./components/create-cpd.component";
import EditCpd from "./components/edit-cpd.component";
import CpdsList from "./components/cpds-list.component";
import DeleteCpd from "./components/cpds-delete.component";
class App extends Component {
render() {
return (
<Router>
<div className="container">
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<Link to="/" className="navbar-brand">MERN-Stack Cpd tracker App</Link>
<div className="collpase navbar-collapse">
<ul className="navbar-nav mr-auto">
<li className="navbar-item">
<Link to="/" className="nav-link">Data List</Link>
</li>
<li className="navbar-item">
<Link to="/create" className="nav-link">Create Cpd data</Link>
</li>
</ul>
</div>
</nav>
<br/>
<Route path="/" exact component={CpdsList} />
<Route path="/edit/:id" component={EditCpd} />
<Route path="/delete/:id" component={DeleteCpd} />
<Route path="/create" component={CreateCpd} />
</div>
</Router>
);
}
}
export default App;
This is the error my getting:
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
in CpdList (created by Context.Consumer)
What I'm trying to do is delete via id. What am I doing wrong?
This is my CPDList:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
// import { CSVLink } from "react-csv";
// import DeleteCpd from './cpd_delete.component';
const Cpd = props => (
<tr>
<td>{props.cpd.cpd_date}</td>
<td>{props.cpd.cpd_activity}</td>
<td>{props.cpd.cpd_hours}</td>
<td>{props.cpd.cpd_learningStatement}</td>
<td>{props.cpd.cpd_evidence}</td>
<td>
<Link to={"/edit/"+props.cpd._id}>Edit</Link>
</td>
<td>
<Link to={"/delete/"+props.cpd._id}>Delete(not working yet)</Link>
</td>
</tr>
)
export default class CpdList extends Component {
constructor(props) {
super(props);
this.state = {
cpds: [],
// csvData:[
// {
// "date": ""
// },
// {
// "activity": ""
// },
// {
// "hours": ""
// },
// {
// "learningStatement": ""
// },
// {
// "evidence": ""
// }
// ]
};
};
// exportCsv()
// {
// var csvRow=[];
// }
componentDidMount() {
axios.get('http://localhost:4000/cpds/')
.then(response => {
this.setState({ cpds: response.data });
})
.catch(function (error){
console.log(error);
});
};
componentDidUpdate() {
axios.get('http://localhost:4000/cpds/')
.then(response => {
this.setState({ cpds: response.data });
})
.catch(function (error){
console.log(error);
});
}
cpdList() {
return this.state.cpds.map(function(currentCpd, i){
return <Cpd cpd={currentCpd} key={i} />;
});
}
render() {
return(
<div>
<h3>Cpd Data List</h3>
<table className="table table-striped" style={{ marginTop: 20 }} >
<thead>
<tr>
<th>Date</th>
<th>Activity</th>
<th>Hours</th>
<th>Learning Statement</th>
<th>Evidence</th>
</tr>
</thead>
<tbody>
{ this.cpdList() }
</tbody>
</table>
{/* <CSVLink data={csvData}
filename={"db.csv"}
color="primary"
style={{float: "left", marginRight: "10px"}}
className="btn btn-primary"
>Download .CSV
</CSVLink> */}
</div>
)
}
};
please ignore the commented out code still working on that.

how to get sending data from restAPI after post response in angular 5?

I have a problem with the output of the json object sent from the server, for some reason I can not get and display the message contained in the response from the server. What am I doing wrong? Thanks for any help.
Below is the code for my application.
service :
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders, HttpRequest } from '#angular/common/http';
import { User } from './user';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import { ResponseObject } from './response-object';
#Injectable()
export class MntApiService {
private mntAPI = 'http://localhost:3000';
constructor(private _http: HttpClient) {
}
getUsers(): Observable<any> {
return this._http.get<any>(this.mntAPI + '/users');
}
addUser(email: string, password: string): Observable<any> {
return this._http.post<any>(this.mntAPI + '/signup', { email, password }, )
.map((response: Response) => response);
}
}
component:
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormBuilder, Validators } from '#angular/forms';
import { HttpErrorResponse, HttpResponse } from '#angular/common/http';
import { Router } from '#angular/router';
import { MntApiService } from '../mnt-api.service';
import { User } from '../user';
import { ResInterceptor } from '../res-interceptor';
#Component({
selector: 'app-signup-page',
templateUrl: './signup-page.component.html',
styleUrls: ['./signup-page.component.scss']
})
export class SignupPageComponent implements OnInit {
users: any = [];
myForm: FormGroup;
response: {
body: {
succes: boolean,
message: string,
status: number
}
};
constructor(
private mntApiService: MntApiService,
private fb: FormBuilder,
public routes: Router) {
}
ngOnInit() {
this.initForm();
}
private initForm(): void {
this.myForm = this.fb.group({
// type: null,
email: [null, [
Validators.required, Validators.email
]],
password: [null, [
Validators.required
]]
});
}
isControlInvalid(controlName: string): boolean {
const control = this.myForm.controls[controlName];
const result: boolean = control.invalid && control.touched;
return result;
}
addUser() {
const val = this.myForm.value;
const controls = this.myForm.controls;
if (this.myForm.invalid) {
Object.keys(controls)
.forEach(controlName => controls[controlName].markAsTouched());
return;
} else {
val.email = val.email.trim();
val.password = val.password.trim();
if (!val.email && !val.password) {
return;
}
this.mntApiService.addUser(val.email, val.password)
.subscribe(user => {
this.users.push(user);
},
response => { this.response = response; });
console.log(this.response);
return;
}
}
}
component.html
<div class="container pt-5">
<form [formGroup]="myForm">
<div class="form-group">
<label for="email">Email address</label>
<small class="form-text text-danger">
{{response?.body.message}}
</small>
<input formControlName="email" type="email" class="form-control" id="email" placeholder="Enter email" autocomplete="email">
<small *ngIf="isControlInvalid('email')" class="form-text text-danger">неправельный формат почты</small>
</div>
<div class="form-group">
<label for="password">Password</label>
<input formControlName="password" type="password" class="form-control" id="password" placeholder="Password"
autocomplete="current-password">
<small *ngIf="isControlInvalid('password')" class="form-text text-danger">это поле не может быть пустым</small>
</div>
<button (click)="addUser()" class="btn btn-primary">Submit
</button>
</form>
</div>
and my node server code:
app.post('/signup', (req, res) => {
let sql = 'SELECT email FROM users WHERE email = ?';
let emailBody = [req.body.email];
config.query(sql, emailBody, (err, userEmail) => {
const errResponse = {
sacces: false,
message: 'Почта занята'
};
const rightResponse = {
'sacces': true,
'message': 'Пользователь создан',
'status': 201
};
if (userEmail.length < 0) {
res.status(409).send(errResponse);
console.log('mail exist!!!!');
return;
} else {
bcrypt.hash(req.body.password, 10, (err, hash) => {
if (err) {
return res.status(500).json({
error: err
});
} else {
let sql = 'INSERT INTO users ( email, password) VALUES ( ?, ?)';
let email = req.body.email;
let password = hash;
let body = [email, password];
config.query(sql, body, (err) => {
if (err) {
res.json({
"message": 'SQL Error'
});
} else {
//res.sendStatus(201);
res.status(201).send(rightResponse);
// res.status(201).json({
// 'message': "Спасибо за регестрацию"
// });
console.log('User created');
return;
}
});
}
});
}
});
});
please help who can, I'm a novice developer .
This is part of your code
this.mntApiService.addUser(val.email, val.password)
.subscribe(user => {
this.users.push(user);
},
response => { this.response = response; });
What you are doing here it that you are passing the subscribe method 2 parameters.
The first parameter is this function
user => {
this.users.push(user);
}
The second parameter is this function
response => { this.response = response; }
The function you pass to subscribe as second parameter gets executed when an error occurs, which I guess is not what you want.
Probably an implementation like this should do the trick for you
this.mntApiService.addUser(val.email, val.password)
.subscribe(response => {
response => { this.response = response; });
// this.users.push(user); CHECK THIS LINE - YOU ARE NOT RECEIVING A USER FROM THE SERVER BUT A MESSAGE
};

How to efficiently show a users change/update

I have a moments component which is similar to a thread/post. Users can like or dislike this moment. Once they like the moment i call the momentService to retrieve the entire list again so it refreshes and increases the like count of the moment.
However, as im only liking one post its not efficient to update all the other moments. Whats the best way to show this update/change without having to get all the moments again.
When i call the update i retrieve the updated moment object. So is there a way to update this specific moment in the moments object.
moments.component.html
<mat-card class="" *ngFor="let moment of moments">
<mat-card-header class="sub-header" fxLayout="row" fxLayoutAlign="space-between center">
<mat-card-subtitle>
{{moment.created_at}}
</mat-card-subtitle>
<mat-card-title>
<img src="http://via.placeholder.com/50x50" alt="" class="img-circle">
</mat-card-title>
<div>
<button mat-icon-button color="warn" matTooltip="Delete" (click)="delete(moment._id)">
<mat-icon>delete</mat-icon>
</button>
<button mat-icon-button>
<mat-icon>more_vert</mat-icon>
</button>
</div>
</mat-card-header>
<mat-card-content>
<p>
{{moment.body}}
</p>
</mat-card-content>
<mat-card-actions fxLayout="row" fxLayoutAlign="space-between center">
<div>
<button mat-icon-button matTooltip="Like" (click)="like(moment._id)">
<mat-icon>thumb_up</mat-icon> {{moment.likes.length}}
</button>
<button mat-icon-button matTooltip="Dislike" (click)="dislike(moment._id)">
<mat-icon>thumb_down</mat-icon> {{moment.dislikes.length}}
</button>
</div>
<button mat-icon-button matTooltip="Comments">
<mat-icon>comment</mat-icon> {{moment.comments.length}}
</button>
</mat-card-actions>
</mat-card>
moment.component.ts
import { Component, OnInit } from '#angular/core';
import { AuthService } from '../../../services/auth.service';
import { MomentService } from '../../../services/moment.service';
import { Router, ActivatedRoute, ParamMap } from '#angular/router';
import { UserService } from '../../../services/user.service';
#Component({
selector: 'app-moments',
templateUrl: './moments.component.html',
styleUrls: ['./moments.component.scss']
})
export class MomentsComponent implements OnInit {
user: any;
moments: any;
constructor(private authService: AuthService,
private userService: UserService,
private momentService: MomentService,
private route: ActivatedRoute,
private router: Router) { }
ngOnInit() {
this.route.parent.paramMap.switchMap((params: ParamMap) => {
let user_id = params.get('id');
return this.userService.get(user_id);
}).subscribe((res) => {
this.user = res;
console.log(this.user._id);
this.getMoments();
});
}
getMoments() {
this.momentService.all(this.user._id).subscribe((res) => {
this.moments = res.data;
}, (err) => {
console.log(err);
});
}
like(moment) {
let like = { 'like': this.user._id };
this.momentService.update(moment, like).subscribe((res) => {
this.getMoments();
console.log(res);
}, (err) => {
console.log(err);
});
}
dislike(moment) {
let dislike = { 'dislike': this.user._id };
this.momentService.update(moment, dislike).subscribe((res) => {
this.getMoments();
console.log(res);
}, (err) => {
console.log(err);
});
}
delete(moment) {
let id = moment;
this.momentService.delete(id).subscribe((res) => {
this.getMoments();
console.log(res);
}, (err) => {
console.log(err);
})
}
}
moments.service.ts
import { HttpParams } from '#angular/common/http';
import { Injectable } from '#angular/core';
import { ApiService } from './api.service';
#Injectable()
export class MomentService {
path = 'moment/';
constructor(private apiService: ApiService) { }
create(user_id, moment) {
let endpoint = this.path;
return this.apiService.post(endpoint, moment);
}
delete(moment_id) {
let endpoint = this.path + moment_id;
return this.apiService.delete(endpoint);
}
all(user_id) {
let endpoint = this.path;
let params = new HttpParams().set('author', user_id);
return this.apiService.get(endpoint, params);
}
get(moment_id) {
let endpoint = this.path + moment_id;
return this.apiService.get('endpoint');
}
update(moment_id, data) {
let endpoint = this.path + moment_id;
return this.apiService.put(endpoint, data);
}
search(filters) {
let endpoint = this.path;
let params = new HttpParams().set('filters', filters);
return this.apiService.get(endpoint, params);
}
}
moment.controller.js (backend api)
update(req, res) {
let id = req.params.id;
Moment.findOne({ '_id': id }, (err, moment) => {
if (req.body.body) {
moment.body = req.body.body;
}
// LIKE&DISLIKE Toggle
if (req.body.like) {
if (moment.dislikes.indexOf(req.body.like) > -1) {
moment.dislikes.remove(req.body.like);
}
if (moment.likes.indexOf(req.body.like) > -1) {
moment.likes.remove(req.body.like);
} else {
moment.likes.push(req.body.like);
}
}
if (req.body.dislike) {
if (moment.likes.indexOf(req.body.dislike) > -1) {
moment.likes.remove(req.body.dislike);
}
if (moment.dislikes.indexOf(req.body.dislike) > -1) {
moment.dislikes.remove(req.body.dislike);
} else {
moment.dislikes.push(req.body.dislike);
}
}
moment.save((err, moment) => {
if (err) {
return res.status(404).json({
success: false,
status: 404,
data: {},
mesage: "Failed to update moment"
});
}
return res.status(201).json({
succss: true,
status: 201,
data: moment,
message: "Succesfully updated moment",
});
});
})
}
Instead of passing the id to the like/dislike methods, you can pass the entire object and from there pass the id to the update method, and on success, mutate the reference.

Resources