MEAN - Http Put Request 404 Not Found - node.js

I am building a MEAN stack application. I am receiving a 404 response when submitting a put request.This only occurs when I am trying to edit a booking. It does not successfully edit a specific booking.
Client Side
booking.service.ts
getBooking(id: string) {
return this.http.get<{ _id: string, title: string, content: string }>("http://localhost:3000/api/bookings/" + id);
}
updateBooking(id: string, title: string, content: string){
const booking: Booking = { id: id, title: title, content: content };
this.http.put("http://localhost:3000/api/bookings/" + id, booking)
.subscribe((response) => {
const id = booking.id;
const updateBook = [...this.bookings];
const oldBookingIndex = updateBook.findIndex(b => b.id === id);
updateBook[oldBookingIndex] = booking;
this.bookings = updateBook;
this.bookingUpdate.next([...this.bookings]);
});
}
booking-create.component.html
<mat-card>
<form (submit)="onSaveBooking(bookingForm)" #bookingForm="ngForm">
<mat-form-field>
<input matInput type="date" name="title" [ngModel]="booking?.title"
required minlength="3"
#title="ngModel"
placeholder="Date">
<mat-error *ngIf="title.invalid">Please enter title</mat-error>
</mat-form-field>
<mat-form-field>
<textarea matInput name="content" [ngModel]="booking?.content" required
#content="ngModel" placeholder="Golf Course"></textarea>
<mat-error *ngIf="content.invalid">Please enter content</mat-error>
</mat-form-field>
<hr>
<button mat-button
color="accent"
type="submit">Save Booking</button>
</form>
</mat-card>
booking-create.component.ts
import { Component, OnInit } from '#angular/core';
//import {Booking } from '../booking-list/booking.model';
import { NgForm } from '#angular/forms';
import { BookingService } from '../booking.service';
import { ActivatedRoute, ParamMap } from '#angular/router';
import { Booking } from '../booking-list/booking.model';
#Component({
selector: 'app-booking-create',
templateUrl: './booking-create.component.html',
styleUrls: ['./booking-create.component.css']
})
export class BookingCreateComponent implements OnInit {
enteredTitle = '';
enteredContent = '';
booking: Booking;
private mode = 'create';
private bookingId: string;
constructor(public bookingService: BookingService, public route: ActivatedRoute) { }
ngOnInit() {
this.route.paramMap.subscribe((paramMap: ParamMap) => {
if (paramMap.has('bookingId')){
this.mode = 'edit';
this.bookingId = paramMap.get('bookingId');
this.bookingService.getBooking(this.bookingId).subscribe(bookingData => {
this.booking = {id: bookingData._id, title: bookingData.title, content: bookingData.content};
});
}
else {
this.mode = 'create';
this.bookingId = null;
}
});
}
//bookingCreated = new EventEmitter<Booking>();
onSaveBooking(form: NgForm){
if(form.invalid){
return;
}
if (this.mode === 'create') {
this.bookingService.addBooking(form.value.title, form.value.content);
}
else {
this.bookingService.updateBooking(this.bookingId, form.value.title, form.value.content);
}
form.resetForm();
}
}
Server side
app.js
app.get("/api/bookings/:id", (req, res, next) => {
Booking.findById(req.params.id).then(booking => {
if (booking) {
res.status(200).json(booking);
}
else {
res.status(404).json({ message: 'Booking not found'});
}
})
});
app.put("/api/bookings/:id", (req, res, next) => {
const booking = new Booking({
_id: req.body.id,
title: req.body.title,
content: req.body.content
});
Booking.updateOne({_id: req.params.id}, booking).then(result => {
console.log(result);
res.status(200).json({message: 'Booking updated'});
});
});

I guess when you are use using 'booking' in this line that throws an issue
Booking.updateOne({_id: req.params.id}, booking).then(result => {
You can try just to use a single params to see if it is working
{$set: {"title": req.body.title}}
Not sure if the whole object can be passed like that.

Related

Upload MULTIPLE files in Angular (with Multer. Node and Express)

i have my multer uploading part:
news.js
const express = require('express');
const router = require("express").Router();
const multer = require('multer');
const News = require('../models/news');
const mongoose = require('mongoose');
const DIR = './public/'
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, DIR)
},
filename: (req, file, cb) => {
const fileName = file.originalname.toLowerCase().split(' ').join('-')
cb(null, fileName)
},
})
//Mime Type Validation
var upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 5,
},
fileFilter: (req, file, cb) => {
if (
file.mimetype == 'image/png' ||
file.mimetype == 'image/jpg' ||
file.mimetype == 'image/jpeg'
) {
cb(null, true)
} else {
cb(null, false)
return cb(new Error('Only .png, .jpg and .jpeg format allowed!'))
}
},
})
router.post('/news', upload.array('photos', 4), (req, res, next) => {
const reqFiles = [];
const url = req.protocol + '://' + req.get('host')
for (var i = 0; i < req.files.length; i++) {
reqFiles.push(url + '/public/' + req.files[i].filename)
}
const news = new News({
_id: new mongoose.Types.ObjectId(),
title: req.body.title,
subtitle: req.body.subtitle,
text: req.body.text,
photos: reqFiles,
})
news
.save()
.then((result) => {
console.log(result)
res.status(201).json({
_id: result._id,
title: result.title,
subtitle: result.subtitle,
text: result.text,
photos: result.photos,
})
})
.catch((err) => {
console.log(err),
res.status(500).json({
error: err,
})
})
})
router.get('/', (req, res, next) => {
News.find().then((data) => {
res.status(200).json({
message: 'News retrieved successfully!',
news: data,
})
})
})
router.get('/:id', (req, res, next) => {
News.findById(req.params.id).then((data) => {
if (data) {
res.status(200).json(post)
} else {
res.status(404).json({
message: 'Not found!',
})
}
})
})
module.exports = router;
and my template with form and file input:
news-photo-uploader.component.html
<form
[formGroup]="form"
(ngSubmit)="submitForm()"
action="/news"
method="POST"
enctype="multipart/form-data">
<div class="form-group">
<input
type="file"
(change)="uploadFile($event)"
name="photos"
multiple/>
</div>
<div class="form-group">
<button type="submit">Add new post</button>
</div>
<!-- Image Preview -->
<div class="form-group">
<div class="preview" *ngIf="preview && preview !== null">
<img [src]="preview" [alt]="form.value.name" />
</div>
</div>
</form>
when i send POST request with Postman, everything works fine and i receive all (2) my image links
{
"_id": "63330b3d9b83959f4b65ba75",
"photos": [
"http://localhost:3000/public/2022-4-15_16-36-4.211.jpg",
"http://localhost:3000/public/img_20220301_210457.jpg"
]
}
but, when i try to do it with my Angular app
news.service.ts
import { News } from '../../data/interfaces/news';
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs';
import { HttpHeaders, HttpClient, HttpEvent } from '#angular/common/http';
import { ApiService } from 'src/app/shared/service/api.service';
#Injectable({
providedIn: 'root',
})
export class NewsService {
path: string = '/news';
constructor(private http: HttpClient, private apiService: ApiService) {}
// Get News
getNews(): Observable<{ news: News[] }> {
return this.apiService.get(this.path);
}
// Create News
addNews(title: string, subtitle: string, text: string, newsImages: Array<File>): Observable<HttpEvent<any>> {
var formData: any = new FormData();
formData.append('title', title);
formData.append('subtitle', subtitle);
formData.append('text', text);
// formData.append('photos', newsImages);
for(let i = 0; i < newsImages.length; i++){
formData.append('photos', newsImages[i]);
}
console.log(formData);
return this.http.post<News>(`${this.apiService.url}/news`, formData, {
reportProgress: true,
observe: 'events',
});
}
}
news-photo-uploader.component.ts
import { NewsService } from './../../news.service';
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormGroup } from '#angular/forms';
import { HttpEvent, HttpEventType } from '#angular/common/http';
import { Router } from '#angular/router';
#Component({
selector: 'app-news-photo-uploader',
templateUrl: './news-photo-uploader.component.html',
styleUrls: ['./news-photo-uploader.component.scss'],
})
export class NewsPhotoUploaderComponent implements OnInit {
preview!: string;
form: FormGroup;
percentDone?: any = 0;
users: any[] = [];
constructor(public fb: FormBuilder, public router: Router, public newsService: NewsService) {
// Reactive Form
this.form = this.fb.group({
title: [''],
subtitle: [''],
text: [''],
photos: [null],
});
}
ngOnInit(): void {}
uploadFile(event: any) {
const file = (event.target as HTMLInputElement).files![0];
this.form.patchValue({
photos: file,
});
this.form.get('photos')!.updateValueAndValidity();
// File Preview
const reader = new FileReader();
reader.onload = () => {
this.preview = reader.result as string;
};
reader.readAsDataURL(file);
}
submitForm() {
this.newsService
.addNews(this.form.value.title, this.form.value.subtitle, this.form.value.text, this.form.value.photos)
.subscribe((event: HttpEvent<any>) => {
switch (event.type) {
case HttpEventType.Sent:
console.log('Request has been made!');
break;
case HttpEventType.ResponseHeader:
console.log('Response header has been received!');
break;
}
});
}
}
then all i receive in my console or DB is empty array instead list of links
photos:[]
subtitle:""
text:""
title:""
_id:"63330f199b83959f4b65ba7b"
what should i need to do in my news.service.ts to make it fixed?

How to update the user feed after updating the post?

I have a UserFeed component and EditForm component. As soon as I edit the form, I need to be redirected to the UserFeed and the updated data should be shown on UserFeed(title and description of the post).
So, the flow is like-UserFeed, which list the posts, when click on edit,redirected to EditForm, updates the field, redirected to UserFeed again, but now UserFeed should list the posts with the updated data, not the old one.
In this I'm just redirectin to / just to see if it works. But I need to be redirected to the feed with the updated data.
EditForm
import React, { Component } from "react";
import { connect } from "react-redux";
import { getPost } from "../actions/userActions"
class EditForm extends Component {
constructor() {
super();
this.state = {
title: '',
description: ''
};
handleChange = event => {
const { name, value } = event.target;
this.setState({
[name]: value
})
};
componentDidMount() {
const id = this.props.match.params.id
this.props.dispatch(getPost(id))
}
componentDidUpdate(prevProps) {
if (prevProps.post !== this.props.post) {
this.setState({
title: this.props.post.post.title,
description: this.props.post.post.description
})
}
}
handleSubmit = () => {
const id = this.props.match.params.id
const data = this.state
this.props.dispatch(updatePost(id, data, () => {
this.props.history.push("/")
}))
}
render() {
const { title, description } = this.state
return (
<div>
<input
onChange={this.handleChange}
name="title"
value={title}
className="input"
placeholder="Title"
/>
<textarea
onChange={this.handleChange}
name="description"
value={description}
className="textarea"
></textarea>
<button>Submit</button>
</div>
);
}
}
const mapStateToProps = store => {
return store;
};
export default connect(mapStateToProps)(EditForm)
UserFeed
import React, { Component } from "react"
import { getUserPosts, getCurrentUser } from "../actions/userActions"
import { connect } from "react-redux"
import Cards from "./Cards"
class UserFeed extends Component {
componentDidMount() {
const authToken = localStorage.getItem("authToken")
if (authToken) {
this.props.dispatch(getCurrentUser(authToken))
if (this.props && this.props.userId) {
this.props.dispatch(getUserPosts(this.props.userId))
} else {
return null
}
}
}
render() {
const { isFetchingUserPosts, userPosts } = this.props
return isFetchingUserPosts ? (
<p>Fetching....</p>
) : (
<div>
{userPosts &&
userPosts.map(post => {
return <Cards key={post._id} post={post} />
})}
</div>
)
}
}
const mapStateToPros = state => {
return {
isFetchingUserPosts: state.userPosts.isFetchingUserPosts,
userPosts: state.userPosts.userPosts.userPosts,
userId: state.auth.user._id
}
}
export default connect(mapStateToPros)(UserFeed)
Cards
import React, { Component } from "react"
import { connect } from "react-redux"
import { compose } from "redux"
import { withRouter } from "react-router-dom"
class Cards extends Component {
handleEdit = _id => {
this.props.history.push(`/post/edit/${_id}`)
}
render() {
const { _id, title, description } = this.props.post
return (
<div className="card">
<div className="card-content">
<div className="media">
<div className="media-left">
<figure className="image is-48x48">
<img
src="https://bulma.io/images/placeholders/96x96.png"
alt="Placeholder image"
/>
</figure>
</div>
<div className="media-content" style={{ border: "1px grey" }}>
<p className="title is-5">{title}</p>
<p className="content">{description}</p>
<button
onClick={() => {
this.handleEdit(_id)
}}
className="button is-success"
>
Edit
</button>
</div>
</div>
</div>
</div>
)
}
}
const mapStateToProps = state => {
return {
nothing: "nothing"
}
}
export default compose(withRouter, connect(mapStateToProps))(Cards)
updatePost action
export const updatePost = (id, data, redirect) => {
return async dispatch => {
dispatch( { type: "UPDATING_POST_START" })
try {
const res = await axios.put(`http://localhost:3000/api/v1/posts/${id}/edit`, data)
dispatch({
type: "UPDATING_POST_SUCCESS",
data: res.data
})
redirect()
} catch(error) {
dispatch({
type: "UPDATING_POST_FAILURE",
data: { error: "Something went wrong"}
})
}
}
}
I'm not sure if my action is correct or not.
Here's the updatePost controller.
updatePost: async (req, res, next) => {
try {
const data = {
title: req.body.title,
description: req.body.description
}
const post = await Post.findByIdAndUpdate(req.params.id, data, { new: true })
if (!post) {
return res.status(404).json({ message: "No post found "})
}
return res.status(200).json({ post })
} catch(error) {
return next(error)
}
}
One mistake is that to set the current fields you need to use $set in mongodb , also you want to build the object , for example if req.body does not have title it will generate an error
updatePost: async (req, res, next) => {
try {
const data = {};
if(title) data.title=req.body.title;
if(description) data.description=req.body.description
const post = await Post.findByIdAndUpdate(req.params.id, {$set:data}, { new: true })
if (!post) {
return res.status(404).json({ message: "No post found "})
}
return res.status(200).json({ post })
} catch(error) {
return next(error)
}
}

MEAN Stack NodeJS PUT requestion code is not being run

I have created a simple booking app where using the MEAN stack. The app is working fine for the GET functionality. But for some reason my PUT code will just not run i.e. I have added console.log to try and write to the console when the PUT code runs. But this code is not being hit at all. I have tried using Postman to test if the functionality works and Postman works. See my code below:
export class Tank {
id: string;
date: string;
tankNumber: number;
sessionOne: boolean;
sessionTwo: boolean;
sessionThree: boolean;
sessionFour: boolean;
sessionFive: boolean;
constructor(
id: string,
date: string,
tankNumber: number,
sessionOne: boolean,
sessionTwo: boolean,
sessionThree: boolean,
sessionFour: boolean,
sessionFive: boolean
) {
this.id = id;
this.date = date;
this.tankNumber = tankNumber;
this.sessionOne = sessionOne;
this.sessionTwo = sessionTwo;
this.sessionThree = sessionThree;
this.sessionFour = sessionFour;
this.sessionFive = sessionFive;
}
}
Below is my HTML code that sends the booking request:
<mat-card *ngIf="dateSelectionButtonPressed">
<mat-card-header>
<mat-card-title>Tank 1</mat-card-title>
</mat-card-header>
<mat-card-content *ngFor="let session of tankAvailability; let i = index">
<div class="tank-one" *ngIf="session.tankNumber == 1">
<button *ngIf="session.sessionOne === false" mat-raised-button color="primary" (click)="bookSession(session.id, session.date, session.tankNumber, session.sessionOne = true, session.sessionTwo, session.sessionThree, session.sessionFour, session.sessionFive)">07.00</button>
<button *ngIf="session.sessionTwo === false" mat-raised-button color="primary" (click)="bookSession(session.id, session.date, session.tankNumber, session.sessionOne, session.sessionTwo = true, session.sessionThree, session.sessionFour, session.sessionFive)">09.00</button>
<button *ngIf="session.sessionThree === false" mat-raised-button color="primary" (click)="bookSession(session.id, session.date, session.tankNumber, session.sessionOne, session.sessionTwo, session.sessionThree = true, session.sessionFour, session.sessionFive)">11.00</button>
<button *ngIf="session.sessionFour === false" mat-raised-button color="primary" (click)="bookSession(session.id, session.date, session.tankNumber, session.sessionOne, session.sessionTwo, session.sessionThree, session.sessionFour = true, session.sessionFive)">13.00</button>
<button *ngIf="session.sessionFive === false" mat-raised-button color="primary" (click)="bookSession(session.id, session.date, session.tankNumber, session.sessionOne, session.sessionTwo, session.sessionThree, session.sessionFour, session.sessionFive = true)">15.00</button>
</div>
</mat-card-content>
</mat-card>
Below is my booking code:
import { Component, OnInit, OnDestroy } from '#angular/core';
import { Tank } from '../../models/tank.model';
import { FormGroup, FormControl } from '#angular/forms';
import { TankService } from 'src/app/services/tank.service';
#Component({
selector: 'app-booking',
templateUrl: './booking.component.html',
styleUrls: ['./booking.component.css']
})
export class BookingComponent implements OnInit, OnDestroy {
private tankSub: Subscription;
// public payPalConfig?: IPayPalConfig;
selectedDate: any;
convertedDate: string;
dateSelectionButtonPressed = false;
tankAvailability: Tank[] = [];
tankOneAvailability: string[] = [];
tank: Tank;
constructor(private tankService: TankService) { }
bookSession(id, date, tankNumber, sessionOne, sessionTwo, sessionThree, sessionFour, sessionFive) {
const tank = new Tank(id, date, tankNumber, sessionOne, sessionTwo, sessionThree, sessionFour, sessionFive);
this.tankService.updateTankWithNewBooking(tank);
}
}
Below is my service for sending the Tank object along with ID to the back end server:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Subject } from 'rxjs';
import { map } from 'rxjs/operators';
import { Tank } from '../models/tank.model';
#Injectable({
providedIn: 'root'
})
export class TankService {
private tanks: Tank[] = [];
private tanksUpdate = new Subject<Tank[]>();
constructor(private httpClient: HttpClient) { }
// Update tank with new booked session
updateTankWithNewBooking(tank: Tank) {
console.log(tank);
return this.httpClient.put<{ message: string }>('http://localhost:3000/api/tank/' + tank.id, tank);
}
}
Below is my backend server side NodeJS code:
const express = require('express');
const bodyParser = require('body-parser')
const mongoose = require('mongoose');
const TankSchemaModel = require('./models/tank');
const app = express();
mongoose.connect('xxxxxxx', { useNewUrlParser: true })
.then(() => {
console.log('Connected to database!');
})
.catch((err) => {
console.log(err + 'Connection failed!!');
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
res.setHeader(
"Access-Control-Allow-Methods",
"GET, POST, PUT, PATCH, DELETE, OPTIONS"
);
next();
});
// create a tank
app.post('/api/tank', (req, res, next) => {
const tank = new TankSchemaModel({
date: '22-08-2019',
tankNumber: 1,
sessionOne: false,
sessionTwo: true,
sessionThree: false,
sessionFour: false,
sessionFive: true
/* date: req.body.date,
tankNumber: req.body.tankNumber,
sessionOne: req.body.sessionOne,
sessionTwo: req.body.sessionTwo,
sessionThree: req.body.sessionThree,
sessionFour: req.body.sessionFour,
sessionFive: req.body.sessionFive */
});
// save tank to database
tank.save().then(createdTankDetails => {
res.status(201).json({
message: 'Tank detals created successfully!',
tankId: createdTankDetails._id
});
});
});
// get all tank data
app.get('/api/tanks', (req, res, next) => {
TankSchemaModel.find().then(documents => {
res.status(200).json({
message: 'Tank data fetched successfully',
tanks: documents
});
});
});
// get tank data by date
app.get('/api/tanks/:date', (req, res, next) => {
TankSchemaModel.find( { date: { $eq: req.params.date } } ).then(documents => {
res.status(200).json({
message: 'Tank details successfully fetched!',
tanks: documents
});
});
});
// edit a tank
app.put('/api/tank/:id', (req, res, next) => {
console.log("Beans!");
console.log(req.params.id);
console.log(req.body);
console.log(req.body.date);
TankSchemaModel.findOneAndUpdate({ _id: req.params.id },
{
$set: {
// _id: req.body.id,
date: req.body.date,
tankNumber: req.body.tankNumber,
sessionOne: req.body.sessionOne,
sessionTwo: req.body.sessionTwo,
sessionThree: req.body.sessionThree,
sessionFour: req.body.sessionFour,
sessionFive: req.body.sessionFive
}
}, (err, result) => {
if(err) {
console.log(err);
res.status(401).json({
message: 'Tank booking failed!'
});
} else {
res.status(200).json({
message: 'Tank booking updated successfully!'
});
}
});
});
module.exports = app;

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