The value is not sent from dropdown to Express.js - html

I want to send the values of a form to Express.js to then save them in database. But the only value that is not reaching Express.js is the value in the select element. The form sends two things it sends an excel file and the value inside the select element. I even tried to console.log the req.body to see if the value is sent in the request body but it returns a void {} value. Here is the HTML.
<div class="w3-card-2 w3-display-middle" class="margin:auto">
<header class="w3-container w3-blue"><h4><b>Subir documento de Excel</b></h4></header>
<form id="uploadForm" enctype="multipart/form-data" action="/upload" method="post">
<br>
<input type="file" name="file" />
<br>
<br>
<label>Entidad financiera: </label>
<select name="bancos" class="w3-select w3-border"> /* <---------- */
<option value="noAsignado">No asignado</option>
<option value="bhdLeon">BHD Leon</option>
<option value="asociacionNacional">ASOCIACION NACIONAL DE AHORROS Y PRESTAMOS</option>
<option value="pucmm">PUCMM</option>
<option value="grupoAltus">GRUPO ALTUS</option>
</select>
<br>
<br>
<br>
<br>
<input class="w3-display-bottommiddle" type="submit" value="Subir" name="submit">
</form>
Here the Node code:
app.post('/upload', function(req, res){
console.log(req.body); // <---------------------
var exceltojson;
upload(req, res, function(err){
if (err) {
res.json({error_code:1,err_desc:err});
return;
}
if(!req.file){
res.json({error_code:1, err_desc:"No file passed"});
return;
}
if(req.file.originalname.split('.')[req.file.originalname.split('.').length-1] === 'xlsx'){
exceltojson = xlsxtojson;
} else {
exceltojson = xlstojson;
}
try {
exceltojson({
input: req.file.path,
output: "./outPutJSON/output.json",
lowerCaseHeaders: true
}, function(err, result){
if(err){
return res.json({error_code:1, err_desc:err, data: null});
}
res.json({datos:"Los datos fueron agregados exitosamente"});
fs.readFile("./outPutJSON/output.json", 'utf8', async (err, fileContents) => {
if (err) {
console.error(err);
return;
}
try {
let data = JSON.parse(fileContents);
console.log(data); //--------------HERE THE EXCEL FILE WHEN IS PARSED
io.emit('test event', 'Se han subido ' + data.length + ' casos' );
for(let cantidad = 0; cantidad < data.length; cantidad++){
var documento = data[cantidad];
if(documento.nombre === '' || documento.cedula === '' || documento.direccion === '') {
console.log('No se puede guardar este documento');
} else {
var mostrar = await incrementar();
documento.caso = mostrar;
documento.montoApoderado = data[cantidad]['monto apoderado'];
documento.numeroCliente = data[cantidad]['no.cliente'];
documento.numeroProducto = data[cantidad]['no.producto'];
let today = moment().format('YYYY M D');
documento.fechaCreado = today;
var mod = new model(documento);
await mod.save(documento);
}
}
} catch(err) {
console.error(err);
}
})
});
var fs = require('fs');
try {
fs.unlinkSync(req.file.path)
}catch(e){
}
} catch (e) {
res.json({error_code:1, err_desc:"Corrupted excel file"});
}
});
});

1-) Check that your express.js use the next sentences before calling the router methods:
app.use(bodyParser);
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: false })); // support encoded bodies
2-) You don't have an ID attribute attached to your tag and NAME attributes to select options (although the name is the one necessary for the server-side... :/)
You need to re-write your js code:
<select id="banks" name="bancos" class="w3-select w3-border"> /* <---------- */
<option name="noAsignado" value="noAsignado">No asignado</option>
<option name="bhdLeon" value="bhdLeon">BHD Leon</option>
<option name="asociacionNacional" value="asociacionNacional">ASOCIACION NACIONAL DE AHORROS Y PRESTAMOS</option>
<option name="pucmm" value="pucmm">PUCMM</option>
<option name="grupoAltus" value="grupoAltus">GRUPO ALTUS</option>
</select>
3-) Maybe you are checking the body before going through the next() function. Try before executing the handler and there, check the req.body again. :)
Best regards.

Related

How to populate ejs form dropdown list options from MySQL database?

<div class="form-group">
<label for="Station_Type">Station Type</label>
<select name="Station_Type" class="form-control" name="Station_Type" id="Station_Type" autocomplete="off">
<option>Sewing</option>
<option>Cutting</option>
<option>Finishing</option>
<option>Distribution</option>
<option>Ironing</option>
<option>Offline</option>
</select>
</div>
I want the option values of this dropdown field to be populated by values stored in a separate table named 'stationoptions' in MySQL database which will be constantly updated. Right now, the options are hardcoded as shown in my code above, however, I want the dropdown list to be automatically updated whenever new values are added to the 'stationoptions' table in MySQL. May I know how do I query the data from MySQL to this form field?
This is how I insert the data from this form into another separate table. (in my .js file)
addPlayerPage: (req, res) => {
res.render('add-player.ejs', {
title: "Welcome | Add a new transaction",
message: ''
});
},
addPlayer: (req, res) => {
let playerId = req.params.id;
let LineNo = req.body.LineNo;
let Station_Type = req.body.Station_Type;
let query = "INSERT INTO `lineid` (id, LineNo, Station_Type) VALUES (NULL, '" + LineNo + "', '" + Station_Type + "')";
db.query(query, (err, result) => {
if (err) {
return res.status(500).send(err);
}
});
res.redirect('/line');
},
Try this:
<div class="form-group">
<label for="Station_Type">Station Type</label>
<select id="Station_Type" name="Station_Type" class="form-control" placeholder="Station_Type" value="<%= playerLine.Station_Type %>" required>
<!-- for loop code start -->
<% for(var i=0; i < playerLine.length; i++) { %>
<option value="<%= playerLine[i].Station_Type %>"><%= playerLine[i].Station_Type %></option>
<% } %>
<!-- for loop code end -->
<!-- and maybe you can remove this part -->
<option value="<%= playerLine.Station_Type %>"><%= playerLine.Station_Type %></option>
<option>Sewing</option>
<option>Cutting</option>
<option>Finishing</option>
<option>Distribution</option>
<option>Ironing</option>
<option>Offline</option>
<!-- and maybe you can remove this part -->
</select>
</div>
EDIT
In your js file:
addPlayerPage: (req, res) => {
// query the table you want show in your ejs
let myQuery = "SELECT field_name FROM table_name;" // query for the dropdown
db.query(myQuery , function(err, result) {
if (err) {
return res.status(500).send(err); // check if query have error
}
res.render('add-player.ejs', {
title: "Welcome | Add a new transaction",
message: '',
drecord: result // setting result reference for ejs
});
})
},
addPlayer: (req, res) => {
let playerId = req.params.id;
let LineNo = req.body.LineNo;
let Station_Type = req.body.Station_Type;
let query = "INSERT INTO `lineid` (id, LineNo, Station_Type) VALUES (NULL, '" + LineNo + "', '" + Station_Type + "')";
db.query(query, (err, result) => {
if (err) {
return res.status(500).send(err);
}
});
res.redirect('/line');
},
In you add-player.ejs:
<div class="form-group">
<label for="Station_Type">Station Type</label>
<select id="Station_Type" name="Station_Type" class="form-control" placeholder="Station_Type" required>
<!-- for loop code start -->
<% for(var i=0; i < drecord.length; i++) { %>
<option value="<%= drecord[i].field_name %>"><%= drecord[i].field_name %></option>
<% } %>
<!-- for loop code end -->
</select>
</div>

HTML Form Concatenate Inputs into One Field (with GET)

Long story short:
<form action="example.com/" method="get">
<input type="hidden" name="q" value="one,two,">
<input type="text" name="q">
</form>
The goal is that, when the user inputs e.g. "three", the website
example.com/?q=one,two,three
is called, instead of example.com/?q=one,two,&q=three.
A solution without JavaScript would be ideal, but I suspect that's not possible.
Thank you so much!
If you don't mind using an array then you can try using this solution
<form action="example.com/" method="GET">
<input type="hidden" name="q[]" value="one">
<input type="hidden" name="q[]" value="two">
<input type="text" name="q[]">
<input type="submit" name="submit">
</form>
this way you will get an array of values on submit then you can handle it on server side. But if you just still want to use your method then Javascript is required. With javascript you can get formdata then append the user input to the form then send it using ajax.
Yes, it's not possible without using Javascript as far I know.
it's better if you handle this at the backend.
But, if you really want to do at the front-end, you can do as follows (With vanilla Javascript).
document.addEventListener("DOMContentLoaded", function(){
let form = document.getElementById('form');
let query = '';
let valueObj = {};
if(form){
form.addEventListener('submit', (e) => {
e.preventDefault();
let exceptinput = ['submit','reset','button','file','image'];
let allElem = e.srcElement;
if(allElem.length > 0){
createValueObj(allElem, valueObj, exceptinput).then(data => {
console.log(data);
query = serialize(data);
window.location = 'http://www.example.com/?' + query;
}).catch(err => {
console.log(err);
})
}
});
}
let serialize = (obj) => {
var str = [];
for (var p in obj)
if (obj.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
}
let insertValueToObj = (key, value, obj) => {
if(obj[key]){
obj[key] = obj[key]+','+ value;
}else{
obj[key] = value;
}
return obj;
}
let createValueObj = (arr, obj, exceptinput) => {
return new Promise((resolve, reject)=>{
for (let index = 0; index < arr.length; index++) {
let isProperInput = exceptinput.includes(arr[index].type);
if(!isProperInput) {
let key = arr[index].name;
let value = arr[index].value.trim();
obj = insertValueToObj(key, value, obj);
}
if(index == (arr.length -1)){
resolve(obj);
}
}
});
}
});
thanks.

Get the data after redirect

I've a page '/order/new' that include 2 dropdown menues for customer & its address & a button that redirect to choose product to add to the order and I get the products in an array and pass the array to the '/order/new'..but when i redirect I don't get the selected customer & its address..I save the products which will be added in order in global array called hh which its get the data from ajax
I want to get the customer & its address after adding the product array
global.hh = new Array();
module.exports = {
getProduct: (req , res ) => {
var products = req.query.selectedProduct;
var total = req.query.sumTotal;
var btekh = hh.push(products)
}
getOrderProduct: (req , res) => {
let query1 = "SELECT * FROM `product`";
getConnection().query(query1 ,(err , result) => {
if(err) {
return res.status(500).send(err);
}
res.render('productOrder.ejs' , {
products: result
});
});
},
addOrderProduct: (req, res) => {
res.redirect('/order/new')
}
postOrder: (req ,res) => {
var products = req.session.products;
getConnection().query('INSERT INTO `order` ( clientId , addressId,orderStatusId) VALUES (?,?,?)', [req.body.selectUser, req.body.selectAddress,req.body.selectedStatus], (err,result) => {
if (err) {
console.log(err);
}
hh.slice(-1)[0].forEach(function (item) {
let insertedOrder = result.insertId;
let query = "INSERT INTO `orderProduct`( `orderIdProduct`, `productId`, `orderProductName`,`orderProductPrice`, `orderProductQuantity`, `orderProductTotal`) VALUES (?,?,?,?,?,?)";
getConnection().query( query , [insertedOrder,item.check,item.name,item.p,item.q,item.total] , (err , result)=>{
if (err) {
console.log(err);
}
res.end();
})
})
})
}
res.redirect('/')
}
app.get('/order/new' , addOrderPage)
app.use('/postOrder' , postOrder);
app.use('/order/product' , getProduct);
my ajax code:
////////////////add users's address///////////////////////////
$('#user').change(function(){
var item = $('#user').val();
$.ajax({
type:'GET',
data: { selectedId: item },
url:'/users/address',
success: function(data){
$('#address').empty();
$('address').append("<option disabled selected> Select Address..</option>");
$.each(data, function (index, addressObj) {
$('#address').append("<option value = '" + addressObj.addressId + "' > " + addressObj.addressName + " </option > ");
});
}
});
})
;
//////////////get the product to order/////////////
$('#save').click(function () {
var orderProduct = new Array();
$("#table input[type=checkbox]:checked").each(function () {
var row = $(this).closest("tr");
var message0 = row.find('#check').val();
var message1 = row.find('.name').text().trim();
var message3 = row.find('.currency').text().trim();
var message4 = row.find(".foo").val();
const result = {check: message0,name: message1,p: message3,q: message4 ,total: message3 * message4}
var hh = orderProduct.push(result);
});
console.log(orderProduct);
var totalPrice = 0;
orderProduct.forEach(function (item , index) {
totalPrice = totalPrice + item.total
})
$.ajax({
type: 'GET',
data: {selectedProduct: orderProduct , sumTotal: totalPrice},
url: '/order/product',
success: function (data) {
console.log(data);
}
})
})
My ejs for'/new/order':
<header>
<h2>New Order : </h2>
</header>
<form action="/postOrder" method="post" id="newForm" >
<label> User Name:</label>
<select name="selectUser" id="user" >
<option disabled selected> Select User..</option>
<% users.forEach((users) => { %>
<option value="<%= users.id %>" > <%=users.name %> </option>
<% }) %>
</select>
<br>
<label>Address :</label>
<select name="selectAddress" id="address">
<option disabled selected> Select Address..</option>
</select>
<br>
<label>Product</label>
add product
<br>
<label>Status</label>
<select name="selectedStatus">
<% status.forEach((status) => { %>
<option value="<%= status.statusId %>"> <%= status.statusText %></option>
<% }) %>
</select>
<br>
<input type="submit" value="Save">
</form>
in these lines,
res.render('productOrder.ejs' , {
products: result
});
are you successfully getting all products from your DB back?
because in your AJAX call,
$.ajax({
type: 'GET',
data: {selectedProduct: orderProduct , sumTotal: totalPrice},
url: '/order/product',
success: function (data) {
console.log(data);
}
})
you're sending data, but not using it in your 'query1' here,
let query1 = "SELECT * FROM `product`";
I'm trying to get the flow of your program.
So the user goes to your webpage, they select a product, your webpage pings your REST server with the product information, your REST server pings your database looking for that product, then that data is rendered to this template here?
res.render('productOrder.ejs' , {
products: result
});
EDIT: You have to handle the user interaction with event listeners and the user input with some storage method.
Your_client-side_JS_script.js
function handle_submit(e) {
e.preventDefault();
if (e.target.id === 'addProduct') {
// When they click add product, you need to either pass their user details to the route and send them with the $.ajax GET request
//... and keep track of the data like that
// OR
// track that data in a cookie,
read up on cookies https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie
} else if (e.target.id === 'newForm') {
console.log("Submit Form");
}
};
$('#addProduct').on('click', handle_submit);
$('#newForm').on('submit', handle_submit);
I recommend the cookie method. You set the cookie once, use it when you need it, then delete it when you're done.
With the first method, you have to send the data in your fetch (which doesn't need that data to get the products), then you have to manage that user_data throughout your back-end making sure it doesn't get lost. It's too much work. Use the cookie method instead.

Accessing the data inside a array of json object to auto select a value in the dropdown

How can i auto select the value from a dropdown by comparing with the data from my angular model.
json :
{"EmployeeI9Docs":[
{"List":"","DocumentTypeId":7,"DocumentTitle":"Driver's license or ID card","DocumentIssuer":"DMV","DocumentNumber":"D998799","ExpirationDate":"2019-11-21T00:00:00"}
]
}
js file :
EVerifyModule.controller('EVerifyI9Controller', ['$scope', '$http', 'EVerifyModuleI9Service', function ($scope, $http, EVerifyModuleI9Service) {
$scope.i9doctypes = [];
//Get the employee Info
EVerifyModuleI9Service.getEmployeeInformation(sessionStorage.ceId).then(function (response) {
if (response != null) {
alert(response.data.EmployeeInfo.DocumentTitle);
$scope.employeeInfo = response.data.EmployeeInfo;
}
});
// Get the doc types (Lookup) for Dropdowns ListA, ListB, ListC.
EVerifyModuleI9Service.GetI9DocTypes().then(function (response) {
$scope.i9doctypes = response.data;
});
}]);
HTML :
<div>
<select name="ListA" class="form-control input-md"
ng-disabled="selectedOptionB || selectedOptionC"
ng-model="employeeInfo.EmployeeI9Docs[0].DocumentTitle"
data-toggle="tooltip"
data-original-title="{{selectedOptionA.description}}"
ng-options="doc.brief for doc in i9doctypes | filter:{list:'A'} | orderBy:'index' track by doc.id">
<option value=""> </option>
</select>
</div>
Two things need to change.
1. ng-model should be something like
$scope.selectedEmployeeId;
Change ng-options to:
ng-options="doc.DocumentNumber as doc.DocumentNumber for doc in i9doctypes"

Adding a picture to the MEAN.JS sample with Angular-file-upload

I am using MEAN.JS (https://github.com/meanjs/mean) and angular-file-upload (https://github.com/danialfarid/angular-file-upload).
The "Article" sample provided by MEAN.JS contains two fields named "title" and "content". I want to modify that and add a "picture" field allowing a user to upload a picture.
I understand that I have to modify 3 files in MEAN.JS:
~myproject/app/models/article.server.model.js
~myproject/public/modules/articles/controllers/articles.client.controller.js
~myproject/public/modules/articles/views/create-article.client.view.html
However, I can not modify them successfully.
My solution uses angular-file-upload on the client and uses connect-multiparty to handle the file upload.
The images are stored directly in the database which limits their size. I have not included the required code to check the image size.
set up
bower install ng-file-upload --save
bower install ng-file-upload-shim --save
npm i connect-multiparty
npm update
all.js
add angular-file-upload scripts
...
'public/lib/ng-file-upload/FileAPI.min.js',
'public/lib/ng-file-upload/angular-file-upload-shim.min.js',
'public/lib/angular/angular.js',
'public/lib/ng-file-upload/angular-file-upload.min.js',
...
config.js
Inject angular-file-upload dependency
...
var applicationModuleVendorDependencies = ['ngResource', 'ngAnimate', 'ui.router', 'ui.bootstrap', 'ui.utils', 'angularFileUpload'];
...
article.client.controller.js
Use angular-file-upload dependency
angular.module('articles').controller('ArticlesController', ['$scope', '$timeout', '$upload', '$stateParams', '$location', 'Authentication', 'Articles',
function($scope, $timeout, $upload, $stateParams, $location, Authentication, Articles) {
$scope.fileReaderSupported = window.FileReader !== null;
// Create new Article
$scope.create = function(picFile) {
console.log('create');
console.log(picFile);
var article = new Articles({
title: this.title,
content: this.content,
image: null
});
console.log(article);
$upload.upload({
url: '/articleupload',
method: 'POST',
headers: {'Content-Type': 'multipart/form-data'},
fields: {article: article},
file: picFile,
}).success(function (response, status) {
$location.path('articles/' + response._id);
$scope.title = '';
$scope.content = '';
}).error(function (err) {
$scope.error = err.data.message;
});
};
$scope.doTimeout = function(file) {
console.log('do timeout');
$timeout( function() {
var fileReader = new FileReader();
fileReader.readAsDataURL(file);
console.log('read');
fileReader.onload = function(e) {
$timeout(function() {
file.dataUrl = e.target.result;
console.log('set url');
});
};
});
};
$scope.generateThumb = function(file) {
console.log('generate Thumb');
if (file) {
console.log('not null');
console.log(file);
if ($scope.fileReaderSupported && file.type.indexOf('image') > -1) {
$scope.doTimeout(file);
}
}
};
}
create-article.client.view.html
update the create view to handle file selection and upload
<section data-ng-controller="ArticlesController">
<div class="page-header">
<h1>New Article</h1>
</div>
<div class="col-md-12">
<form name="articleForm" class="form-horizontal" data-ng-submit="create(picFile)" novalidate>
<fieldset>
<div class="form-group" ng-class="{ 'has-error': articleForm.title.$dirty && articleForm.title.$invalid }">
<label class="control-label" for="title">Title</label>
<div class="controls">
<input name="title" type="text" data-ng-model="title" id="title" class="form-control" placeholder="Title" required>
</div>
</div>
<div class="form-group">
<label class="control-label" for="content">Content</label>
<div class="controls">
<textarea name="content" data-ng-model="content" id="content" class="form-control" cols="30" rows="10" placeholder="Content"></textarea>
</div>
</div>
<div class="form-group">
<label class="control-label" for="articleimage">Article Picture</label>
<div class="controls">
<input id="articleimage" type="file" ng-file-select="" ng-model="picFile" name="file" accept="image/*" ng-file-change="generateThumb(picFile[0], $files)" required="">
<br/>
<img ng-show="picFile[0].dataUrl != null" ng-src="{{picFile[0].dataUrl}}" class="img-thumbnail" height="50" width="100">
<span class="progress" ng-show="picFile[0].progress >= 0">
<div style="width:{{picFile[0].progress}}%" ng-bind="picFile[0].progress + '%'" class="ng-binding"></div>
</span>
<span ng-show="picFile[0].result">Upload Successful</span>
</div>
</div>
<div class="form-group">
<input type="submit" class="btn btn-default" ng-disabled="!articleForm.$valid" ng-click="uploadPic(picFile)">
</div>
<div data-ng-show="error" class="text-danger">
<strong data-ng-bind="error"></strong>
</div>
</fieldset>
</form>
</div>
</section>
view-article.client.view.html
update list view to include image
<img ng-src="data:image/jpeg;base64,{{article.image}}" id="photo-id" width="200" height="200"/>
list-articles.client.view.html
update view to include imgae
<img ng-src="data:image/jpeg;base64,{{article.image}}" id="photo-id" width="40" height="40"/>
article.server.model.js
Add image to database model
...
image: {
type: String,
default: ''
},
...
article.server.routes.js
Add new route for upload use connect-multiparty
...
multiparty = require('connect-multiparty'),
multipartyMiddleware = multiparty(),
...
app.route('/articleupload')
.post(users.requiresLogin, multipartyMiddleware, articles.createWithUpload);
...
article.server.controller.js
Handle new route for upload require fs
...
fs = require('fs'),
...
/**
* Create a article with Upload
*/
exports.createWithUpload = function(req, res) {
var file = req.files.file;
console.log(file.name);
console.log(file.type);
console.log(file.path);
console.log(req.body.article);
var art = JSON.parse(req.body.article);
var article = new Article(art);
article.user = req.user;
fs.readFile(file.path, function (err,original_data) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
}
// save image in db as base64 encoded - this limits the image size
// to there should be size checks here and in client
var base64Image = original_data.toString('base64');
fs.unlink(file.path, function (err) {
if (err)
{
console.log('failed to delete ' + file.path);
}
else{
console.log('successfully deleted ' + file.path);
}
});
article.image = base64Image;
article.save(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(article);
}
});
});
};
...
Thanks Charlie Tupman for this last solution which works very well.
I simply add the dependencies :
...
multiparty = require('multiparty'),
uuid = require('uuid'),
...
before the exports function and changed two lines to improve the behavior:
...
var destPath = './public/uploads/' + fileName;
article.image = '/uploads/' + fileName;
...
which resolve in:
exports.createWithUpload = function(req, res) {
var form = new multiparty.Form();
form.parse(req, function(err, fields, files) {
var file = req.files.file;
console.log(file.name);
console.log(file.type);
console.log(file.path);
console.log(req.body.article);
var art = JSON.parse(req.body.article);
var article = new Article(art);
article.user = req.user;
var tmpPath = file.path;
var extIndex = tmpPath.lastIndexOf('.');
var extension = (extIndex < 0) ? '' : tmpPath.substr(extIndex);
var fileName = uuid.v4() + extension;
var destPath = './public/uploads/' + fileName;
article.image = '/uploads/' + fileName;
var is = fs.createReadStream(tmpPath);
var os = fs.createWriteStream(destPath);
if(is.pipe(os)) {
fs.unlink(tmpPath, function (err) { //To unlink the file from temp path after copy
if (err) {
console.log(err);
}
});
article.save(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(article);
}
});
} else
return res.json('File not uploaded');
});
};
My working solution in MEAN.js
server model:
image:{
type: String,
default: ''
},
server controller:
var item = new Item(JSON.parse(req.body.item));
item.user = req.user;
if(req.files.file)
item.image=req.files.file.name;
else
item.image='default.jpg';
//item.image=
item.save(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(item);
}
});
server route: (requires multer: "npm install multer --save")
var multer = require('multer');
app.use(multer({ dest: './public/uploads/'}));
frontend angular controller:
$scope.image='';
$scope.uploadImage = function(e){
console.log(e.target.files[0]);
$scope.image=e.target.files[0];
};
// Create new Item
$scope.create = function() {
// Create new Item object
var item = new Items ({
name: this.name,
bought: this.bought,
number: this.number,
description: this.description,
warranty: this.warranty,
notes: this.notes
});
ItemsService.saveItem(item,$scope.image);
};
service which send's the request:
.factory('ItemsService', ['$http','$rootScope', function($http, $rootScope)
{
var service={};
service.saveItem = function(item, image)
{
var fd = new FormData();
fd.append('file', image);
fd.append('item', JSON.stringify(item));
$http.post('items/', fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
console.log('success add new item');
})
.error(function(e){
console.log('error add new item', e);
});
};
return service;
}
]);
html view:
<div class="form-group">
<label class="control-label" for="name">Image</label>
<div class="controls">
<input type="file" data-ng-model="image" id="image" my-file-upload="uploadImage" required>
{{selectedFile.name}}
</div>
</div>
#john prunell Thank you so much for this, I finally figured it out (took me over a week but i am now much more comfortable with the stack) I have forked it to get it to upload the file to a folder:
'exports.createWithUpload = function(req, res) {
var form = new multiparty.Form();
form.parse(req, function(err, fields, files) {
var file = req.files.file;
console.log(file.name);
console.log(file.type);
console.log(file.path);
console.log(req.body.article);
var art = JSON.parse(req.body.article);
var article = new Article(art);
article.user = req.user;
var tmpPath = file.path;
var extIndex = tmpPath.lastIndexOf('.');
var extension = (extIndex < 0) ? '' : tmpPath.substr(extIndex);
var fileName = uuid.v4() + extension;
var destPath = './uploads/' + fileName;
article.image = fileName;
var is = fs.createReadStream(tmpPath);
var os = fs.createWriteStream(destPath);
if(is.pipe(os)) {
fs.unlink(tmpPath, function (err) { //To unlink the file from temp path after copy
if (err) {
console.log(err);
}
});
article.save(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(article);
}
});
}else
return res.json('File not uploaded');
});
};
What I would like to do now is fork your solution to allow uploading of multiple images in the same way, if you have any insight into how to do this that would be amazing, I will let you know how I get on.