MongoDB - Error with Postman - Data sending fails - node.js

I have used Mean Stack to build a project. I have created a Report Form in which data can be inserted.
When I insert the data from the form the data is inserted to the collection.
But when I use Postman to insert data the data insertion fails.
Here are the code segments:
1.Front End Form - report.component.html
<form (ngSubmit)="savereportdata()" novalidate>
<ba-card>
<div class="form-group">
<label for="middleItemId">Item ID</label>
<input type="text" class="form-control" placeholder="Enter Item ID" [(ngModel)]="itemId" name="itemId">
</div>
<div class="form-group">
<label for="middleItemName">Item Name</label>
<input type="text" class="form-control" placeholder="Enter Item Name" [(ngModel)]="itemName" name="itemName">
</div>
<div class="form-group">
<label for="warrentyUntil">Warrenty Until</label>
<input type="date" readonly="" class="form-control">
</div>
<div class="form-group">
<label for="reportDescription">Description</label>
<textarea class="form-control" rows="3" [(ngModel)]="reportDescription" name="reportDescription"></textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</ba-card>
</form>
2.report.component.ts
import { NgModule,Component,Pipe,OnInit } from '#angular/core';
import { ReportItemService } from '../../../services/report-item.service'
#Component({
selector: 'app-report',
templateUrl: './report.component.html'
})
export class ReportComponent implements OnInit {
itemId:Number;
itemName:String;
reportDescription:String;
constructor(public reportservice:ReportItemService) {}
ngOnInit() {}
savereportdata() {
const reportitem = {
itemId:this.itemId,
itemName:this.itemName,
reportDescription:this.reportDescription
};
this.reportservice.reportitemdata(reportitem).subscribe(res=> {
console.log(res);
});
}
}
3.report-item.service.ts
import { Injectable } from '#angular/core';
import { Http,Headers} from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class ReportItemService {
reportitem:any;
constructor(private http:Http) {}
reportitemdata(reportitem) {
let headers=new Headers();
headers.append('Content-Type','application/json');
return this.http.post("http://localhost:3000/reportItem",reportitem,{headers:headers}).map(res=>res.json());
}
}
4.Backend Model - report.js
const mongoose = require('mongoose');
const schema = mongoose.Schema;
const reportSchema = new schema({
itemId: { type: Number, required: true },
itemName: { type: String },
reportDescription: { type: String },
date: { type: Date }
});
module.exports = mongoose.model("ReportItem", reportSchema);
module.exports.saveReportItem = function(newreport, callback) {
console.log(newreport);
newreport.save(callback);
};
5.router - reportItem.js
const express = require('express');
const router = express.Router();
const config = require('../config/database');
const ReportItem = require('../models/request-report/report');
router.post("", function(req, res) {
const newreport = new ReportItem({
itemId: req.body.itemId,
itemName: req.body.itemName,
reportDescription: req.body.reportDescription,
date: new Date
});
ReportItem.saveReportItem(newreport, function(err, report) {
if (err) {
res.json({ state: false, msg: "data not inserted" });
}
if (report) {
res.json({ state: true, msg: "data inserted" });
}
});
});
module.exports = router;
The Screenshot of the results when data is inserted from the form:
The Screenshot of the Error in Postman:
I've been trying to figure out this problem for weeks but couldn't.
Thanks loads in advance!

You could try using the bodyParser module in the js code to grab the data from the request. I’ve had issues with this in the past.

Related

request body empty when send form data to node js rest API

I created an HTML form to store data into MSSQL
This is the form:
<form [formGroup]="insProtocolloForm" (ngSubmit)="sumit()" enctype="multipart/form-data">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="newProtInStaticBackdropLabel">Nuovo protocollo in entrata</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="dataEmissione">Data Emissione</label>
<input formControlName="dataEmissione" id="dataEmissione" name="dataEmissione" type="text" class="form-control" />
</div>
<div class="form-group">
<label for="anno">Anno</label>
<input formControlName="anno" id="anno" name="anno" type="text" class="form-control" />
</div>
<div class="form-group">
<label for="sede">Sede</label>
<input formControlName="sede" id="sede" name="sede" type="text" class="form-control" />
</div>
<div class="form-group">
<label for="entrataUscita">#Entrata Uscita</label>
<input formControlName="entrataUscita" id="entrataUscita" name="entrataUscita" type="text" class="form-control" />
</div>
<div class="form-group">
<label for="fileToUpload">File</label>
<input formControlName="fileToUpload" id="fileToUpload" name="fileToUpload" type="file" class="form-control" (change)="onFilechange($event)" />
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Annulla</button>
<button type="submit" class="btn btn-success">Inserisci</button>
</div>
</div>
</div>
</form>
And this is the component.ts
import { Component, OnInit } from '#angular/core';
import { CrudService } from '../service/crud.service';
import { DatePipe } from '#angular/common'
import { HttpClient } from '#angular/common/http';
import { FormGroup, FormControl, Validators} from '#angular/forms';
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
insProtocolloForm = new FormGroup({
dataEmissione: new FormControl('', [Validators.required]),
anno: new FormControl('', [Validators.required]),
sede: new FormControl('', [Validators.required]),
entrataUscita: new FormControl('', [Validators.required]),
fileToUpload: new FormControl('', [Validators.required]),
fileSource: new FormControl('', [Validators.required])
});
constructor(private crudService: CrudService, private http: HttpClient) { }
get f(){
return this.insProtocolloForm.controls;
}
onFilechange(event: any) {
//console.log(event.target.files[0])
if (event.target.files.length > 0) {
const fileToUpload = event.target.files[0];
this.insProtocolloForm.patchValue({
fileSource: fileToUpload
});
}
}
sumit() {
console.log('### INIZIO SUBMIT() ###');
const formData = new FormData();
formData.append('dataEmissione', this.insProtocolloForm.get('dataEmissione')?.value);
formData.append('anno', this.insProtocolloForm.get('anno')?.value);
formData.append('sede', this.insProtocolloForm.get('sede')?.value);
formData.append('entrataUscita', this.insProtocolloForm.get('entrataUscita')?.value);
formData.append('fileToUpload', this.insProtocolloForm.get('fileSource')?.value);
console.log(formData);
if (this.insProtocolloForm.get('fileSource')?.value) {
this.http.post('http://localhost:8090/api/inserisci-protocollo', formData)
.subscribe(res => {
console.log('res: ' + res);
alert('Uploaded Successfully.');
});
} else {
alert("Si prega di scegliere un file da caricare")
}
console.log('### FINE SUBMIT() ###');
}
ngOnInit(): void { }
}
On submit I call the Node JS REST API
const sqlController = require('./controllers/dboperations-sql');
const express = require('express');
const cors = require('cors');
const multer = require('multer');
const storage = multer.memoryStorage()
const upload = multer({ storage: storage })
const app = express();
const router = express.Router();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use('/api', router);
app.use(upload.single());
router.use((request,response,next)=>{
next();
})
//Inserisco un nuovo protocollo -> /inserisci-protocollo
router.route('/inserisci-protocollo').post((request,response)=>{
console.log('### Requested: Insert new Protocol ###');
/*request.on('data', data => {
console.log(data.toString());
});*/
let newProtocollo = request.body;
//console.log(newProtocollo);
sqlController.addProtocollo(newProtocollo).then(result => {
response.status(201).json(result);
})
})
And here is the problem. The request.body is always empty.
But if I enable the "request.on('data', data => {..." code, I see all form fields.
I also tried to send data with postman but I have the same result.
With postman, if I set the "form-data" option, the body is always empty, but if I set the "x-www-form-urlencoded" option I see all data except the file.
Can anyone help me to solve this problem?
I've read a lot of posts about it but haven't been able to find a solution yet.
I'm going crazy
Thank you very much
Adriano
You need to add the content type headers in the request from angular's http client.
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'multipart/form-data'
})
};
this.http.post('http://localhost:8090/api/inserisci-protocollo', formData, httpOptions)

How upload image in angular 7 from backend

i can upload image with postman but in angular it doesn't work for me. solution please
error : cannot read originalname of undefined , in nodejs but with
postman its work !
//backend
var express = require("express")
var router = express.Router();
var userModel = require("../models/userModel")
const jwt= require("jsonwebtoken")
const bcrypt=require("bcrypt")
var app=express()
var io = require('socket.io-client')('http://localhost:3000/alll')
var socket = require("socket.io");
var fs=require("fs")
var multer=require("multer")
const upload = multer({dest: __dirname + '/upload/images'});
router.post('/uploads', upload.single('image'), function (req, res) {
var file = __dirname + '/upload' + req.file.originalname;
fs.readFile(req.file.path, function (err, data) {
fs.writeFile(file, data, function (err) {
if (err) {
console.error(err);
var response = {
message: 'Sorry, file couldn\'t be uploaded.',
filename: req.file.originalname
};
} else {
response = {
message: 'File uploaded successfully',
filename: req.file.originalname
};
res.json(response);
}
})
})
})
router.post("/add",function (req, res) {
user = new userModel({firstName: req.body.firstName,
lastName: req.body.lastName ,
email:req.body.email ,
password:req.body.password,
adresse:req.body.adresse,
verif:'1',role :'user',
annonces:req.body.annonces,
pdf: req.body.pdf
})
user.save(function(err) {
if (err) {
res.send({"state": "not ok", "msg": "err:" + err})
} else {
res.send({"state": " ok", "msg": "ajout"})
}
})
})
// model : pdf as String
//ts
import {ChangeDetectorRef, Component, OnInit, TemplateRef} from '#angular/core';
import {FormBuilder, FormGroup, Validators} from '#angular/forms';
import {Router} from '#angular/router';
import {UserService} from '../services/user.service';
import {ConnecterComponent} from '../connecter/connecter.component';
import {BsModalRef, BsModalService} from 'ngx-bootstrap/modal';
import { FileUploader } from 'ng2-file-upload';
#Component({
selector: 'app-singin',
templateUrl: './singin.component.html',
styleUrls: ['./singin.component.css']
})
export class SinginComponent implements OnInit {
registrationForm: FormGroup;
submit = false;
fileSelected: File
emailuser: String;
modalRef: BsModalRef;
selectedFiles: FileList;
currentFileUpload: File;
imgURL: any;
imgname;
errorValidImage = '';
URL ='http://localhost:3000/users/uploads';
constructor(private router: Router, private userService: UserService, private formbuilder: FormBuilder , private cd : ChangeDetectorRef, private modalService: BsModalService ) { }
ngOnInit() {
this.registrationForm = this.formbuilder.group({
email: [ '', [ Validators.required, Validators.email]],
password: ['', [ Validators.required, Validators.minLength(8)]],
firstName:['',[ Validators.required]],
lastName: ['', Validators.required],
adresse:['', Validators.required],
pdf:[''],
});
}
get f() {
return this.registrationForm.controls;
}
OnSubmit(){
this.submit = true;
if (this.registrationForm.invalid) {
return;
}
console.log(this.registrationForm.value)
localStorage.setItem('var', '1');
this.userService.updateimagee(this.currentFileUpload).subscribe(res=>{
this.imgname=JSON.parse(JSON.stringify(res['filename']));
this.userService.register(this.registrationForm.value.firstName,this.registrationForm.value.lastName,this.registrationForm.value.email,this.registrationForm.value.password,this.registrationForm.value.adresse,this.registrationForm.value.pdf=this.imgname).subscribe( res => {
console.log(res['status'])
});
this.userService.login(this.registrationForm.value.email,this.registrationForm.value.password).subscribe(res=>{
localStorage.setItem('var', '1')
localStorage.setItem('emailuser',JSON.parse(JSON.stringify(res['data'])).email)
this.emailuser=localStorage.getItem('emailuser')
console.log(res['status'])
console.log(JSON.parse(JSON.stringify(res['data'])).token);
// console.log(JSON.parse(JSON.stringify(res['data'])).id);
var iduser = parseInt(JSON.parse(JSON.stringify(res['data'])).id);
sessionStorage.setItem('id', JSON.parse(JSON.stringify(res['data'])).id);
this.router.navigate(['']);
})
})
}
selectFile(event) {
this.selectedFiles =event.target.files;
this.currentFileUpload = this.selectedFiles.item(0);
console.log(this.currentFileUpload);
const reader = new FileReader();
reader.onload = (event) => {
this.imgURL = reader.result;
};
console.log(this.imgURL);
console.log(reader);
} }
//html
<div class="container">
<form method="POST" class="appointment-form" id="appointment-form" [formGroup]="registrationForm" (ngSubmit)="OnSubmit()" enctype="multipart/form-data">
<h2>education appointment form</h2>
<div class="form-group-1">
<div [class]="form-control" >
<input type="text" class="form-control" formControlName="firstName" placeholder="First Name" [ngClass]="{'is-invalid':submit && f.firstName.errors} " />
<span class="focus-input100" data-placeholder=""></span>
<div *ngIf="submit && f.firstName.errors" class="invalid-feedback">
<div *ngIf="f.firstName.errors.required">firstName is required </div>
</div>
</div>
<div [class]="form-control" >
<input type="text" formControlName="lastName" placeholder="Last Name" class="form-control" [ngClass]="{'is-invalid':submit && f.lastName.errors}" />
<div *ngIf="submit && f.lastName.errors" class="invalid-feedback">
<div *ngIf="f.lastName.errors.required">LastName is required </div>
</div>
</div>
<div [class]="form-control" >
<input type="email" formControlName="email" placeholder="Email" class="form-control" [ngClass]="{'is-invalid':submit && f.email.errors}" />
<div *ngIf="submit && f.email.errors" class="invalid-feedback">
<div *ngIf="f.email.errors.required">Email is required </div>
</div>
</div>
<div [class]="form-control" >
<input type="password" formControlName="password" placeholder="Password" class="form-control" [ngClass]="{'is-invalid':submit && f.password.errors}" />
<div *ngIf="submit && f.password.errors" class="invalid-feedback">
<div *ngIf="f.password.errors.required">Password is required </div>
<div *ngIf="f.password.errors.minlength">Au moins 8 caracteres </div>
</div>
</div>
<div [class]="form-control" >
<input type="text" formControlName="adresse" placeholder="Adresse local" class="form-control" [ngClass]="{'is-invalid':submit && f.adresse.errors}" />
<div *ngIf="submit && f.adresse.errors" class="invalid-feedback">
<div *ngIf="f.adresse.errors.required">Adresse is required </div>
</div>
</div>
<div class="custom-file">
<input type="file" class="custom-file-input" id="customFile" (change)="selectFile($event)" formControlName="pdf" [ngClass]="{'is-invalid':submit && f.pdf.errors}" />
<label class="custom-file-label">Photo de profil</label>
</div>
<div class="form-submit">
<input type="submit" name="submit" id="submit" class="submit" value="Submit" />
</div>
</div>
</form>
</div>
</div>
but console say that there is error in back-end that :
TypeError: Cannot read property 'originalname' of undefined
at C:\Users\hazem\Desktop\pfe\router\user.js:114:47
It seems like you have not used the library ng2-file-upload Try something like this.
import { Component, OnInit } from '#angular/core';
import { FileUploader, FileSelectDirective } from 'ng2-file-upload/ng2-file-upload';
const UploadURL = 'http://localhost:3000/api/upload';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'Upload a File';
public uploader: FileUploader = new FileUploader({url: URL, itemAlias: 'image'});
ngOnInit() {
this.uploader.onAfterAddingFile = (file) => { file.withCredentials = false; };
this.uploader.onCompleteItem = (item: any, response: any, status: any, headers: any) => {
console.log('FileUpload:uploaded:', item, status, response);
alert('File uploaded successfully');
};
}
}
The line
public uploader: FileUploader = new FileUploader({url: URL, itemAlias: 'image'});
is important. make sure you use the same name('image') in you multer middleware,
like this
upload.single('image')

How to get MongoDB data to select option using NodeJS

I am trying to populate MongoDB data to html select option.
This is what I have done so far
I have created a database books and created collection AuthorDB
I manually inserted data (to check if it really is working)
But when I used postman to get data, I get an empty array means no data. (But I have inserted data to AuthorDB collection)
Here is my server.js
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
const BookDB = require('./book-dbmodel');
const AuthorDB = require('./author-dbmodel');
const app = express();
const router = express.Router();
app.use(bodyParser.json());
app.use(cors());
app.use('/books', router);
//connect to books database
mongoose.connect('mongodb://127.0.0.1:27017/books', {useNewUrlParser: true});
const connection = mongoose.connection;
connection.once('open', () => {
console.log("Connected to MongoDB via port 27017");
});
app.listen(4000, () => {
console.log('Listening to port 4000');
});
// add book http://localhost:4000/books/add
router.route('/add').post((req, res) => {
let bookDB = new BookDB(req.body);
bookDB.save().then((bookDB) => {
res.status(200).send(`${bookDB} Added!`);
}).catch((err) => {
res.status(400).send({message: err});
});
});
//get all authors http://localhost:4000/books/authors
router.route('/authors').get((req, res) => {
AuthorDB.find((err, authors) => {
if(err) throw err;
res.status(200).send(authors);
});
});
//get books by author name http://localhost:4000/books/authors/authorName
router.route('/authors/authorName').get((req, res) => {
let authorName = req.params.authorName;
BookDB.find({firstName: {$regex: `${authorName}`, $options: "i"}}, (err, books) => {
if(err) throw err;
res.status(200).send(books);
});
});
And this is my App.js in front-end:
import React, {Component} from 'react';
import axios from 'axios';
const ShowAuthors = (props) => (
<option value={props.author.firstName}>{props.author.firstName}</option>
);
export default class AddBooks extends Component{
constructor(props){
super(props);
this.state = {
authorArray: [],
name: '',
isbn: 0,
author: '',
price: 0,
yearOfPublication: 0,
publisher: ''
}
}
//to get author list on dropdown select
componentDidMount(){
axios.get('http://localhost:4000/books/authors/')
.then(authors => {
console.log(authors.data);
this.setState({
authorArray: authors.data
});
}).catch(err => {
console.log(err);
});
}
getAuthors(){
return this.state.authorArray.map((currentAuthor, id) => {
return <ShowAuthors author={currentAuthor} key={id} />
});
}
onSubmit(){
}
onChangeName(){
}
onChangeISBN(){
}
render(){
return(
<div className="container">
<h1>Add Books</h1>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label htmlFor="book-name">Book Name</label>
<input
value={this.state.name}
onChange={this.onChangeName}
type="text" className="form-control" id="book-name" aria-describedby="emailHelp" placeholder="Book Name"/>
</div>
<div className="form-group">
<label htmlFor="book-isbn">ISBN</label>
<input
value={this.state.isbn}
onChange={this.onChangeISBN}
type="number" className="form-control" id="book-isbn" aria-describedby="emailHelp" placeholder="ISBN"/>
</div>
<div className="form-group">
<label htmlFor="author-name">Authors</label>
<select
className="form-control" name="authors" id="authors">
{this.getAuthors()} {/* this doesn't return anything but an empty array */}
</select>
</div>
<div className="form-group">
<label htmlFor="book-price">Book Price</label>
<input type="number" className="form-control" id="book-price" name="book-price" aria-describedby="emailHelp" placeholder="Book Price"/>
</div>
<div className="form-group">
<label htmlFor="book-year">Published Year</label>
<input type="number" className="form-control" id="book-year" name="book-year" aria-describedby="emailHelp" placeholder="Year"/>
</div>
<div className="form-group">
<label htmlFor="book-publisher">Book Publisher</label>
<input type="number" className="form-control" id="book-publisher" name="book-publisher" aria-describedby="emailHelp" placeholder="Publisher"/>
</div>
</form>
</div>
);
}
}
And this is my mongodb visualization:
And this is my AuthorDB schema model:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
let AuthorDB = new Schema({
firstName: {type: String},
lastName: {type: String},
nationality: {type: String}
});
module.exports = mongoose.model('AuthorDB', AuthorDB);
for mongoose.model() method
The first argument is the singular name of the collection your model
is for. Mongoose automatically looks for the plural, lowercased
version of your model name. Thus, for the example above, the model
Tank is for the tanks collection in the database.
Mongoose trying to be smart and detect the model name, but you can force it to use the collection you want like this:
new Schema({..}, { collection: 'AuthorDB' })
Or when you create the model, like this:
module.exports = mongoose.model('AuthorDB', AuthorDB, 'AuthorDB')
Also you're trying to access this parameter req.params.authorName while it not defined in your route, you're missing : in your route.
router.route('/authors/authorName')
It should be like this:
router.route('/authors/:authorName')
to be able to get the authorName value.

Angular 6 + NodeJS + MongoDB

Hello after searching here i was unable to find something. 2 similar questions hasn't been answered.
im new here sos if you can help with my final project or lead me to a fix i will be more then happy.
after runing ngForm im unable to post and recive the folowing error:
zone.js:2969 POST http://localhost:4200/signup 404 (Not Found)
core.js:1624 ERROR
My form sits inside other component and my routing looks like that:
{
path: 'signup',
component: SignUpComponent,
data: { title: 'signup' },
children: [
{path: '', component: RegistrationComponent},
{path: 'userSettings', component: UserSettingsComponent},
{path: 'userSettings/finish', component: FinishComponent},
]},
Registration.Component.html
<div class="panel panel-primary">
<div class="panel-heading">
{{ test }}
</div>
<div class="panel-body">
<form [formGroup]="angForm" novalidate>
<div class="form-group">
<label class="col-md-4">inputfirstname</label>
<input type="text" class="form-control" formControlName="inputfirstname" #inputfirstname />
</div>
<div *ngIf="angForm.controls['inputfirstname'].invalid && (angForm.controls['inputfirstname'].dirty || angForm.controls['inputfirstname'].touched)" class="alert alert-danger">
<div *ngIf="angForm.controls['name'].errors.required">
Name is required.
</div>
</div>
<div class="form-group">
<label class="col-md-4">lastname</label>
<input type="text" class="form-control" formControlName="inputlastname" #inputlastname/>
</div>
<div *ngIf="angForm.controls['inputlastname'].invalid && (angForm.controls['inputlastname'].dirty || angForm.controls['inputlastname'].touched)" class="alert alert-danger">
<div *ngIf="angForm.controls['inputlastname'].errors.required">
LastName is required.
</div>
</div>
<div class="form-group">
<label class="col-md-4">inputEmail</label>
<input type="text" class="form-control" formControlName="inputEmail" #inputEmail/>
</div>
<div *ngIf="angForm.controls['inputEmail'].invalid && (angForm.controls['inputEmail'].dirty || angForm.controls['inputEmail'].touched)" class="alert alert-danger">
<div *ngIf="angForm.controls['inputEmail'].errors.required">
inputEmail is required.
</div>
</div>
<div class="form-group">
<label class="col-md-4">inputPassword</label>
<input type="text" class="form-control" formControlName="inputPassword" #inputPassword/>
</div>
<div *ngIf="angForm.controls['inputPassword'].invalid && (angForm.controls['inputPassword'].dirty || angForm.controls['inputPassword'].touched)" class="alert alert-danger">
<div *ngIf="angForm.controls['inputPassword'].errors.required">
inputPassword is required.
</div>
</div>
<div class="form-group">
<label class="col-md-4">confirmPassword</label>
<input type="text" class="form-control" formControlName="confirmPassword" #confirmPassword/>
</div>
<div *ngIf="angForm.controls['confirmPassword'].invalid && (angForm.controls['confirmPassword'].dirty || angForm.controls['confirmPassword'].touched)" class="alert alert-danger">
<div *ngIf="angForm.controls['confirmPassword'].errors.required">
confirmPassword is required.
</div>
</div>
<div class="form-group">
<button (click)="addUser(inputfirstname.value, inputlastname.value,inputEmail.value,inputPassword.value,confirmPassword.value)" [disabled]="angForm.pristine || angForm.invalid" class="btn btn-primary">Add</button>
</div>
</form>
</div>
Registration.component.js
import { Component, OnInit, NgModule } from '#angular/core';
import { FormGroup, FormBuilder, Validators } from '#angular/forms';
//import users class
import {UserService} from './../../user.service'
#Component({
selector: 'app-registration',
templateUrl: './registration.component.html',
styleUrls: ['./registration.component.css']
})
export class RegistrationComponent implements OnInit {
angForm: FormGroup;
constructor(private userservice: UserService, private fb: FormBuilder) {
this.createForm();
}
//user form
createForm() {
this.angForm = this.fb.group({
inputfirstname: ['', Validators.required ],
inputlastname: ['', Validators.required ],
inputEmail: ['', Validators.required ],
inputPassword: ['', Validators.required ],
confirmPassword: ['', Validators.required ]
});
}
addUser(inputfirstname, inputlastname, inputEmail, inputPassword, confirmPassword ) {
this.userservice.addUser(inputfirstname, inputlastname, inputEmail, inputPassword, confirmPassword);
}
ngOnInit() {
// //Create a new user object
// this.user = new user({
// firstname:"",lastname:"",email:"", password: { pwd: "" , confirm_pwd: ""}, terms:false})
}
}
user.service.ts
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { FormGroup, FormBuilder, Validators } from '#angular/forms';
#Injectable()
export class UserService {
constructor(private http: HttpClient) { }
addUser(inputfirstname, inputlastname, inputEmail, inputPassword, confirmPassword) {
const uri = 'http://localhost:4200/signup';
const obj = {
inputfirstname: inputfirstname,
inputlastname: inputlastname,
inputEmail: inputEmail,
inputPassword: inputPassword,
confirmPassword: confirmPassword
};
this.http.post(uri, obj)
.subscribe(res => console.log('Done'));
}
}
singup.js on server side
var express = require('express');
//var router = express.Router();
var router =express();
var registrationSchema = require('../models/Registration.js');
/* GET users listing. */
// router.get('/', function(req, res, next) {
// console.log(registrat);
// });
// Defined store route
router.route('/next').post (function(req,res){
var registerData = new registrationSchema(req.body);
registerData.save().then(item=>{
res.status(200).json({'registerData': 'data added successfully'});
})
.catch(err => {
res.status(400).send("unable to save to database");
});
})
// Defined get data(index or listing) route
router.route('/').get(function (req, res) {
console.log(req.body);
registrationSchema.find(function (err, data){
if(err){
console.log(err);
}
else {
res.json(data);
}
});
});
//registration
router.route('/signup').post (async function (req, res) {
//to add validation?
//create new user
var newUser = new registrationSchema(req.body);
console.log('req.body');
var isCreated = await registrationSchema.inputData(newUser).then(result =>{
if (result)
{
console.log(isCreated);
res.status(200).send({success:true,message:"User Created!"})
}
else
console.log(err);
})
})
//login
router.route('/login'), async function (req, res){
}
module.exports = router;
i would like to hear your idea. allready tested the form at root and changing paths. i recive same errors.
last try was to create a form using different way. and again nothing.
thank you for your time,
Best regards!
addUser(inputfirstname, inputlastname, inputEmail, inputPassword, confirmPassword) {
const uri = 'http://localhost:4200/signup';
uri belongs to the server! i mixed up the idea. need to be the server ip + port + callout router from server.
and the submision is wrong. had to restudy the http docs.

How can I use a dropdown in my angular2 form to submit an object

I have an application that will include Topics which contain Articles. When the user creates an article, I want them to select a topic to associate the article with from a dropdown that presents the available topics. The UI side of this presents the user with a form that looks correct at the moment, however, the topic object is not being passed with the form and I cant understand why. Can someone please help me understand how this should be done?
the relevant pieces here are below:
This is the select statement in my form that properly displays the options for topics that I want to present to the user.
<select [ngFormControl]="myForm.find('topic')" id="topic" class="form-control" required>
<option *ngFor="let a of topics" [value]="a">{{a.title}}</option>
</select>
When I try to verify that I received the data I'm looking for I get an 'undefined' error with this line:
console.log(this.myForm.value.topic.title);
If I do this I get [object, object]
console.log(this.myForm.value.topic);
what gets submitted to the service is this:
Object { content: "8th content", title: "8th title", articleId: "57588eaf1ac787521d15ac34", username: "Jason", userId: Object, topicId: undefined }
Can someone please help me understand what I'm missing here to be able to send the result of this form select tag into my Angular2 form?
My entire article-input.component.ts file
import { Component, OnInit } from '#angular/core';
import {Article} from './article';
import {ArticleService} from "./article.service";
import {ErrorService} from "../errors/error.service";
import { FormBuilder, ControlGroup, Validators, Control } from '#angular/common';
import {TopicService} from "../topics/topic.service";
import {Topic} from "../topics/topic";
#Component({
selector: 'my-article-input',
template: `
<section class="col-md-8 col-md-offset-2">
<form [ngFormModel]="myForm" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="title">Title</label>
<input [ngFormControl]="myForm.find('title')" type="text" id="title" class="form-control" #input [value]="article?.title">
</div>
<div class="form-group">
<label for="content">Content</label>
<input [ngFormControl]="myForm.find('content')" type="text" id="content" class="form-control" #input [value]="article?.content">
</div>
<select [ngFormControl]="myForm.find('topic')" id="topic" class="form-control" required>
<option *ngFor="let a of topics" [value]="a">{{a.title}}</option>
</select>
<button type="submit" class="btn btn-primary" [disabled]="!myForm.valid">{{ !article ? 'Add Article' : 'Save Article' }}</button>
<button type="button" class="btn btn-danger" (click)="onCancel()" *ngIf="article">Cancel</button>
</form>
</section>
`
})
export class ArticleInputComponent implements OnInit {
myForm: ControlGroup;
article: Article = null;
constructor(private _fb:FormBuilder, private _articleService: ArticleService, private _errorService: ErrorService, private _topicService: TopicService ) {}
topics: Topic[];
onSubmit() {
console.log(this.myForm.value.topic.title);
if (this.article) {
// Edit
this.article.content = this.myForm.value.content;
this.article.title = this.myForm.value.title;
this.article.topicId = this.myForm.value.topic.topicId;
this._articleService.updateArticle(this.article)
.subscribe(
data => console.log(data),
error => this._errorService.handleError(error)
);
this.article = null;
} else {
const article: Article = new Article(this.myForm.value.content, this.myForm.value.title, null, 'DummyArticleInput', this.myForm.value.topic);
this._articleService.addArticle(article)
.subscribe(
data => {
console.log(data);
this._articleService.articles.push(data);
},
error => this._errorService.handleError(error)
);
}
}
onCancel() {
this.article = null;
}
ngOnInit() {
this.myForm = this._fb.group({
title: ['', Validators.required],
content: ['', Validators.required],
topic: ['', Validators.required]
});
this._articleService.articleIsEdit.subscribe(
article => {
this.article = article;
}
);
this._topicService.getTopics().subscribe(
topics => {
this.topics = topics;
this._topicService.topics = topics
},
error => this._errorService.handleError(error)
);
}
}
So the answer to this is to not use the myForm element with ngFormControl for objects/form field that are going to be references to other objects within the application. Instead what needed to be done was as follows.
Create topics, topic, and a selectedTopic
topics: Topic[];
topic = '';
selectedTopic = '';
Add a select tag with an option tag to the form for a user to be able to select the topic they want by binding with ngModel to 'topic'
<select [ngModel]="topic" (ngModelChange)="onChange($event)">
<option [ngValue]="i" *ngFor="let i of topics">{{i.title}}</option>
</select>
Create an onChange method that will update this.selectedTopic based on the user selecting a topic in the form
onChange(newValue) {
this.selectedTopic = newValue;
console.log(this.selectedTopic);
console.log(this.selectedTopic.topicId);
}
Then in the onSubmit method use the myForm.value's for the info coming from the actual form, and use the databinding on this.selectedTopic for the topic that is being selected
onSubmit() {
if (this.article) {
// Edit
this.article.content = this.myForm.value.content;
this.article.title = this.myForm.value.title;
this.article.topicId = this.selectedTopic;
this._articleService.updateArticle(this.article)
.subscribe(
data => console.log(data),
error => this._errorService.handleError(error)
);
this.article = null;
} else {
const article: Article = new Article(this.myForm.value.content, this.myForm.value.title, null, 'dummyUserName', 'dummyUserId', this.selectedTopic.topicId);
this._articleService.addArticle(article)
.subscribe(
data => {
// console.log('what comes back from addArticle is: ' + JSON.stringify(data));
this._articleService.articles.push(data);
},
error => this._errorService.handleError(error)
);
}
From where we started, we have now gotten to a place where everything works and the object getting created looks like this:
{ "_id" : ObjectId("5758c2e173fd33e04092c87e"), "content" : "c66", "title" : "t66", "user" : ObjectId("5755e5be96162f52a4f01dd8"), "topic" : ObjectId("57572d92e802307d199f0afa"), "__v" : 0 }
For reference, the entire (working) article-input.component.ts file looks like this:
import { Component, OnInit } from '#angular/core';
import {Article} from './article';
import {ArticleService} from "./article.service";
import {ErrorService} from "../errors/error.service";
import { FormBuilder, ControlGroup, Validators, Control } from '#angular/common';
import {TopicService} from "../topics/topic.service";
import {Topic} from "../topics/topic";
#Component({
selector: 'my-article-input',
template: `
<section class="col-md-8 col-md-offset-2">
<form [ngFormModel]="myForm" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="title">Title</label>
<input [ngFormControl]="myForm.find('title')" type="text" id="title" class="form-control" #input [value]="article?.title">
</div>
<div class="form-group">
<label for="content">Content</label>
<input [ngFormControl]="myForm.find('content')" type="text" id="content" class="form-control" #input [value]="article?.content">
</div>
<select [ngModel]="topic" (ngModelChange)="onChange($event)">
<option [ngValue]="i" *ngFor="let i of topics">{{i.title}}</option>
</select>
<button type="submit" class="btn btn-primary" >{{ !article ? 'Add Article' : 'Save Article' }}</button>
<button type="button" class="btn btn-danger" (click)="onCancel()" *ngIf="article">Cancel</button>
</form>
</section>
`
})
export class ArticleInputComponent implements OnInit {
myForm: ControlGroup;
article: Article = null;
constructor(private _fb:FormBuilder, private _articleService: ArticleService, private _errorService: ErrorService, private _topicService: TopicService ) {}
topics: Topic[];
topic = '';
selectedTopic = '';
onChange(newValue) {
this.selectedTopic = newValue;
console.log(this.selectedTopic);
console.log(this.selectedTopic.topicId);
}
onSubmit() {
if (this.article) {
// Edit
this.article.content = this.myForm.value.content;
this.article.title = this.myForm.value.title;
this.article.topicId = this.selectedTopic;
this._articleService.updateArticle(this.article)
.subscribe(
data => console.log(data),
error => this._errorService.handleError(error)
);
this.article = null;
} else {
const article: Article = new Article(this.myForm.value.content, this.myForm.value.title, null, 'dummyUserName', 'dummyUserId', this.selectedTopic.topicId);
this._articleService.addArticle(article)
.subscribe(
data => {
// console.log('what comes back from addArticle is: ' + JSON.stringify(data));
this._articleService.articles.push(data);
},
error => this._errorService.handleError(error)
);
}
}
onCancel() {
this.article = null;
}
ngOnInit() {
this.myForm = this._fb.group({
title: ['', Validators.required],
content: ['', Validators.required],
topic: ['', Validators.required]
});
this._articleService.articleIsEdit.subscribe(
article => {
this.article = article;
}
);
this._topicService.getTopics().subscribe(
topics => {
this.topics = topics;
this._topicService.topics = topics
},
error => this._errorService.handleError(error)
);
}
}
my topic.ts angular model looks like this:
export class Topic {
description: string;
title: string;
username: string;
topicId: string;
userId: string;
constructor (description: string, title: string, topicId?: string, username?: string, userId?: string) {
this.description = description;
this.title = title;
this.topicId = topicId;
this.username = username;
this.userId = userId;
}
}
the article.service.ts looks like this:
addArticle(article: Article) {
const body = JSON.stringify(article);
console.log(body);
const headers = new Headers({'Content-Type': 'application/json'});
const token = localStorage.getItem('token') ? '?token=' + localStorage.getItem('token') : '';
return this._http.post('http://localhost:3000/article' + token, body, {headers: headers})
.map(response => {
const data = response.json().obj;
let article = new Article(data.content, data.title, data._id, data.user.firstName, data.user, data.topicId);
return article;
})
.catch(error => Observable.throw(error.json()));
}
an in the backend in Node my article.js looks like this:
router.post('/', function(req, res, next) {
var decoded = jwt.decode(req.query.token);
User.findById(decoded.user._id, function(err, doc) {
if (err) {
return res.status(401).json({
title: 'An Error occured',
error: err
});
}
var article = new Article({
content: req.body.content,
title: req.body.title,
user: doc,
topic: req.body.topicId
});
console.log(req.body);
article.save(function(err, result){
if (err) {
return res.status(404).json({
title: 'An Error occured',
error: err
});
}
doc.articles.push(result);
doc.save();
res.status(201).json({
article: 'Saved Article',
obj: result
});
});
});
});
I hope this helps others who had the same issue as I did.

Resources