I want to list my json data as checkboxlist. I wrote this code. I'm printing this way. I don't know where I'm doing wrong. I get my jSON data from excel file. textarea comes out as "undefined undefined" . Could you help?
HTML CODE:
<div class="example">
<form enctype="multipart/form-data">
<input id="upload" type=file name="files[]">
</form>
<textarea
id="data"
class="form-control text-area-style"
rows=35
cols=120>
</textarea>
</div>
JS CODE:
function ExcelToJSON() {
var list;
document.getElementById("upload").addEventListener("change", handleFileSelect, false);
this.parseExcel = function(file) {
var reader = new FileReader();
reader.onload = function(e) {
var data = e.target.result;
var workbook = XLSX.read(data, {
type: "binary"
});
workbook.SheetNames.forEach(function(sheetName) {
// Here is your object
var XL_row_object = XLSX.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]);
var json_object = JSON.stringify(XL_row_object);
list = JSON.parse(json_object);
console.log(list);
jQuery().val(json_object);
list.forEach(function() {
$('#data).append(' < input name = "accesories"
type = "checkbox"
value = "'+list.id+'" / > '+list.name+' < br / > ');
});
})
};
reader.onerror = function(ex) {
console.log(ex);
};
reader.readAsBinaryString(file);
};
};
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
var xl2json = new ExcelToJSON();
xl2json.parseExcel(files[0]);
}
list.forEach(function() {
$('#data).append(' < input name = "accesories"
type = "checkbox"
value = "'+list.id+'" / > '+list.name+' < br / > ');
});
})
list does not have the attributes id and name (are undefined), you are iterating over list but you are not using the iterated item.
list.forEach(function(item) { // <= forEach calls for every list item this function with the item as argument
$('#data).append(' < input name = "accesories"
type = "checkbox"
value = "'+item.id+'" / > '+item.name+' < br / > ');
});
})
Hint:
Use the build in Browser Debugger it helps a lot, to understand JS.
With Chrome press F12 and set a breakpoint in the foreach function, then execute your code and it will break on the given line, then you will see all variables in your scope. (In your case you will se that list is an array and don't have id and name as property)
Related
I'm working on a project with the following steps:
Creating the form with multiple images upload
Previewing, remove images on queue before upload
Handling the file input value before submit
Here is my code
var fileList = [];
function toObject(arr) {
var rv = {};
for (var i = 0; i < arr.length; ++i)
rv[i] = arr[i];
return rv;
}
//Image prev
// Multiple images preview in browser
var imagesPreview = function (input, imageContainer) {
if (input.files) {
var filesAmount = input.files.length;
$(imageContainer).html('');
for (i = 0; i < filesAmount; i++) {
var reader = new FileReader();
reader.onload = function (event) {
var html = '<div class="image-item col-sm-6 col-md-4 col-lg-3"><div class="image-wrapper">' +
' <img src="'
+ event.target.result + '"/></div></div>';
$(html).appendTo(imageContainer);
}
var files = input.files;
fileList.push(files[i]);
reader.readAsDataURL(input.files[i]);
}
input.files = toObject(fileList);
}
};
$('#input-image').on('change', function () {
imagesPreview(this, '.image-container');
});
<div class="image-item">
<!-- input the image from user -->
<input id="input-image" type="file" name="photos[]" multiple>
<hr>
<div class="image-container row">
<!-- Previewing the image thumbnail -->
</div>
</div>
My questions: Can I set the value of the input-image with fileList variable because I set it but error occurs
Sry, a bit tired, will not go into depth or solve the hole thing...
There is only one way to change the value of file inputs and that is with another FileList instance. the only way you can get them is with some new api's so it won't work in all browsers. I made a function to help you with that.
var fileList = [];
// only way to change input[type=file] value is with a other FileList instance
// and this is the only way to construct a new FileList
function createFileList(a) {
a = [].slice.call(Array.isArray(a) ? a : arguments)
for (var c, b = c = a.length, d = !0; b-- && d;) d = a[b] instanceof File
if (!d) throw new TypeError('expected argument to FileList is File or array of File objects')
for (b = (new ClipboardEvent('')).clipboardData || new DataTransfer; c--;) b.items.add(a[c])
return b.files
}
// This is what you got to do later when they remove a image
//
// this will trigger a change event so you maybe want to temporary
// turn off the change event listener
//
// input.files = createFileList(fileList)
// Image prev
// Multiple images preview in browser
function imagesPreview(input, imageContainer) {
$(imageContainer).empty();
var URL = window.URL || window.webkitURL;
var $html = $(
'<div class="image-item col-sm-6 col-md-4 col-lg-3">'+
'<div class="image-wrapper"> <img></div></div>'
);
$.each(input.files, function(i, file) {
var $clone = $html.clone()
// could be a good idea to revoke url also
$clone.find('img').attr('src', URL.createObjectURL(file))
$clone.appendTo(imageContainer);
fileList.push(file);
});
}
$('#input-image').on('change', function () {
imagesPreview(this, '.image-container');
});
The other solution is to append each file into a formdata and send the form using ajax
I'd like to create a dropdown menu and display all the files currently in a directory so when the user clicks on an item in that list of files, it prints to console the name of that file.
Here is what I've come up with so far:
HTML
<form method="post">
<select name="DropdownList">
<option value="file1">fileArray[0]</option>
<option value="file2">fileArray[1]</option>
<option value="file3">fileArray[2]</option>
<option value="file4">fileArray[3]</option>
</select>
</form>
The problem with doing this hardcoded is what if there are 10 files instead of 4? Trying to figure a more dynamic approach.
Javascript
document.getElementByName('DropdownList').addEventListener('click', function() {
window.update.forEach(function(d, 'data/baselinedata') {
var f = readStringFromFileAtPath(d);
console.log(f)
});
});
function readStringFromFileAtPath (pathOfFileToReadFrom) {
var request = new XMLHttpRequest();
request.open("GET", pathOfFileToReadFrom, false);
request.send(null);
var returnValue = request.responseText;
return returnValue;
}
I guess I just don't know how to make this to dynamic instead of hardcoding the names in the list. I'm kind of a noob to web programming
Edit:
Just for clarity, all I want to do is populate a dropdown list with the names of files in a directory. So when a user goes to click an item in that list, it will print or log (via console.log()) the contents of that file.
You can use <input type="file"> element with multiple attribute set, create two arrays containing File object and result of FileReader.readAsText() and File objects iterate FileList object at change event of input type="file" element to set .name at <option> element .textConten, .value to index of uploaded File append to <select> element, set .value of <textarea> element to selected option which corresponds to index of File as text within array
<input type="file" multiple><br>
<select></select><br>
<textarea></textarea>
<script>
const [input, select, textarea, reader] = [
document.querySelector("input[type=file]")
, document.querySelector("select")
, document.querySelector("textarea")
, new FileReader
];
let [files, data, fn] = [
[],
[], (file, reader) => new Promise((resolve, reject) => {
reader.onload = () => {
reader.onload = reader.onerror = null;
resolve(reader.result);
}
reader.onerror = reject;
reader.readAsText(file);
})
];
input.onchange = async() => {
select.innerHTML = "";
files.length = data.length = 0;
for (const file of input.files) {
const {
name
} = file;
const option = new Option(name, files.length);
files.push(file);
select.appendChild(option);
let result = await fn(file, reader);
data.push(result);
}
}
select.onchange = () => {
textarea.value = data[select.value];
}
</script>
I am using Visual Studio 2012 Express with Framework 4.5 MVC.
I am also using Angular Js for the first time.
I have a view page that contains the multiple browse (file) button that will be use for upload single image by selecting each of them individually with my form data.
The problem is that by using submit button I am not able to get the images but I got the form data.
I want to get the images with the form data using Angular js.
I have already referred below posts but not getting the solution:
LINK 1
LINK 2
Please anyone help me to solve out this problem, would be appreciated.
I have a sample code for the uploading of multiple image using angularjs.
This link might help you: https://jsfiddle.net/n9tL7cdr/1/
<div ng-app="test">
<div ng-controller="UploadCtrl">
<table>
<tr ng-repeat="i in [1, 2, 3, 4]">
<td>{{i}}</td>
<td>
<input type="file" name="file" onchange="angular.element(this).scope().photoChanged(this.files)" /> </td>
<td>
<img ng-src="{{ image[$index].dataUrl }}" height="50px" />
</td>
</tr>
</table>
</div>
CONTROLLER:
angular.module('test', []);
angular.module('test').controller('UploadCtrl', function ($scope, $timeout) {
// Variable for image.
$scope.image = {
dataUrl: []
};
$scope.fileReaderSupported = window.FileReader != null;
$scope.photoChanged = function (files, index) {
if (files != null) {
var file = files[0];
var index = this.$index; // index of image.
if ($scope.fileReaderSupported && file.type.indexOf('image') > -1) {
$timeout(function () {
var fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onload = function (e) {
$timeout(function () {
$scope.image[index] = {dataUrl: e.target.result}; // Retrieve the image.
});
}
});
}
}
};
});
Here i find the solution using HttpPostedFileBase and Form Collection.
public ActionResult AddImageUpload(IEnumerable<HttpPostedFileBase> files,FormCollection fc )
{
ImageUpload IU = new ImageUpload();
IU.MaterialId = Convert.ToInt32((fc["MaterialId"]).Replace("number:",""));
IU.CategoryId = Convert.ToInt32((fc["CategoryId"]).Replace("number:", ""));
string tr = fc["hdnSub"].ToString();
string result = null;
string Message, fileName, actualFileName;
Message = fileName = actualFileName = string.Empty;
bool flag = false;
//HttpPostedFileBase f= IU.ImageP;
string[] SubAssemblyId = (tr.Split(','));
int i = 0;
string databaseid = null;
for (int j=0 ; j<files.Count(); j++)
{
var fileContent = Request.Files[j];
if (fileContent.FileName != "")
{
databaseid = SubAssemblyId[i];
string fn = DateTime.Now.ToShortDateString().Replace("/", "") + DateTime.Now.TimeOfDay.Hours + DateTime.Now.TimeOfDay.Minutes + DateTime.Now.TimeOfDay.Seconds + DateTime.Now.TimeOfDay.Milliseconds + Path.GetExtension(fileContent.FileName);
fileName = fn;
try
{
if (fileContent != null && fileContent.ContentLength > 0)
{
var inputStream = fileContent.InputStream;
var path = Path.Combine(Server.MapPath("/Images/Product/"), fn);
using (var fileStream = System.IO.File.Create(path))
{
inputStream.CopyTo(fileStream);
}
}
}
catch (Exception)
{
}
}
i++;
}
return RedirectToAction("ImageUpload");
}
I'm trying to find a solution for my previous post: Mongo gives duplicate key error on _id_ field in Meteor application
In order to do that I want to read data from my CSV file at server side, and not from the client.
First I tried the solution in this post Using node-csv and meteor-file to import CSV into a collection but meteor-file isn't compatible anymore with current version of Meteor. I also tried the solution in this post Upload Data to Meteor / Mongo DB but It's also on the client and that solution generates the same error as in my previous post.
After some further research I tried to read the data with the code below. However it doesn't work:
First I created a collection:
Meteor.orders = new Meteor.Collection('Orders');
I defined the following template to read the csv file:
<template name="read_file_orders">
<form class="well form-inline">
<label class="control-label" for="fileInput2">Kies bestand</label>
<input class="input-file" id="fileInput2" type="file" name="files[]">
<Button class="btn btn-primary" id="read_orders">Importeer</button>
<button class="btn btn-danger" id="erase_orders">Wis gegevens</button>
</form>
</template>
This is the client javascript:
Template.read_file_orders.events({
"click #read_orders" : function(e) {
var f = document.getElementById('fileInput2').files[0];
console.log("read file");
readFile(f, function(content) {
Meteor.call('upload',content);
});
}
});
readFile = function(f,onLoadCallback) {
var reader = new FileReader();
reader.onload = function (e){
var contents=e.target.result
onLoadCallback(contents);
}
reader.readAsText(f);
};
And this is the server javascript:
Meteor.startup(function () {
// code to run on server at startup
return Meteor.methods({
upload : function(fileContent) {
console.log("start insert");
import_file_orders(fileContent);
console.log("completed");
}
});
});
import_file_orders = function(file) {
var lines = file.split('%\r\n');
var l = lines.length - 1;
for (var i=0; i < l; i++) {
var line = lines[i];
var line_parts = line.split('|');
var ex_key = line_parts[0];
var ex_name = line_parts[1];
var clin_info = line_parts[2];
var order_info = line_parts[3];
var clinician_last_name = line_parts[4];
var clinician_first_name = line_parts[5];
var clinician_code = line_parts[6];
var clinician_riziv = line_parts[7]
var pat_id = line_parts[8];
Meteor.orders.insert({Patient:pat_id, Exam_code:ex_key, Exam_name:ex_name, Clinical_info:clin_info, Order_info:order_info, Clinician_first:clinician_first_name, Clinician_last:clinician_last_name, Clinician_c_code:clinician_code, Clinician_riziv:clinician_riziv, Planned:null});
console.log("%");
};
When I try reading the file, nothing happens. Only the console logs appear in the server console but there is nothing imported. Even the Orders collection isn't created.
It's clear that I'm doing something wrong but I don't know what exactly. However I think the solution isn't too far. Maybe someone of you can show me the right direction?
Kind regards
EDIT:
In order to revmen's answer here's the full code of my testapp:
test.html:
<head>
<title>test</title>
</head>
<body>
<h1>Welcome to Meteor!</h1>
{{> read_file_orders}}
</body>
<template name="read_file_orders">
<form class="well form-inline">
<label class="control-label" for="fileInput2">Kies bestand</label>
<input class="input-file" id="fileInput2" type="file" name="files[]">
<Button class="btn btn-primary" id="read_orders">Importeer</button>
<button class="btn btn-danger" id="erase_orders">Wis gegevens</button>
</form>
</template>
test.js
Orders = new Mongo.Collection("orders");
if (Meteor.isClient) {
// counter starts at 0
Template.read_file_orders.events({
"click #read_orders" : function(e) {
var f = document.getElementById('fileInput2').files[0];
console.log("read file");
readFile(f, function(content) {
Meteor.call('upload',content);
});
}
});
import_file_orders = function(file) {
console.log("enter function import_file_orders")
var lines = file.split(/\r\n|\n/);
var l = lines.length - 1;
for (var i=0; i < l; i++) {
var line = lines[i];
var line_parts = line.split(',');
var ex_key = line_parts[0];
var ex_name = line_parts[1];
var clin_info = line_parts[2];
var order_info = line_parts[3];
var clinician_last_name = line_parts[4];
var clinician_first_name = line_parts[5];
var clinician_code = line_parts[6];
var clinician_riziv = line_parts[7]
var pat_id = line_parts[8];
var result = Orders.insert({Patient:pat_id, Exam_code:ex_key, Exam_name:ex_name, Clinical_info:clin_info, Order_info:order_info, Clinician:{first:clinician_first_name, last:clinician_last_name, c_code:clinician_code, riziv:clinician_riziv}, Planned:null});
console.log(Orders.findOne(result));
};
}
readFile = function(f,onLoadCallback) {
//When the file is loaded the callback is called with the contents as a string
var reader = new FileReader();
reader.onload = function (e){
var contents=e.target.result
onLoadCallback(contents);
}
reader.readAsText(f);
};
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
Meteor.methods({
upload : function(fileContent) {
console.log("start insert");
import_file_orders(fileContent);
console.log("completed");
}
});
}
You were very close. I just had to make a few changes to get it working.
I don't know what your .csv file looks like, so I made one that's like this:
A1, B1, C1, D1, E1, F1, G1, H1, I1
A2, B2, C2, D2, E2, F2, G2, H2, I2
Your file.split operation wasn't splitting the lines, but was putting everything on one big line. I did it this way and it worked:
var lines = file.split(/\r\n|\n/);
That got individual lines to split into members of the array. Then I assumed that, since you're calling your input a CSV, your values are separated by commas, not pipes. So I changed your line.split to this
var line_parts = line.split(',');
Other changes I made may not be what was causing yours to fail, but this is how I think things are normally done...
Instead of declaring your collection like this
Meteor.orders = new Meteor.Collection('Orders');
I did it like this
Orders = new Mongo.Collection("orders");
Note that this is run by both the server and the client.
Instead of your way of declaring methods on the server, I just put this into server code (not in Meteor.start):
Meteor.methods({
upload : function(fileContent) {
console.log("start insert");
import_file_orders(fileContent);
console.log("completed");
}
});
And, of course, I changed the insert line at the bottom of your import_file_orders function
var result = Orders.insert({Patient:pat_id, Exam_code:ex_key, Exam_name:ex_name, Clinical_info:clin_info, Order_info:order_info, Clinician_first:clinician_first_name, Clinician_last:clinician_last_name, Clinician_c_code:clinician_code, Clinician_riziv:clinician_riziv, Planned:null});
console.log(Orders.findOne(result));
EDIT for updated code in the question:
Move the import_file_orders function from the client block to the server block.
i have the following code, the issue i have is that i am getting a error of e.originalEvent.dataTransfer is undefined.
my code is as follows
HTML
Select images: <input type="file" id='fileupload' name="userfile[]" multiple>
Javascript is as follows
var hot = $('#fileupload');
hot.change(function (e)
{
e.preventDefault();
var files = e.originalEvent.dataTransfer.files;
//send dropped files to Server
handleFileUpload(files,hot);
});
function handleFileUpload(files,obj)
{
for (var i = 0; i < files.length; i++)
{
var fd = new FormData();
var e = document.getElementById("child_id");
fd.append('userfile[]', files[i]);
var filename=files[i].name;
var status = new createStatusbar(obj,files[i]); //Using this we can set progress.
status.setFileNameSize(files[i].name,files[i].size);
sendFileToServer(fd,status,filename);
}
}
The attribute files belongs to the input field. This you'll get by the target attribute.
If I test the setting above, I have success with this descriptor:
e.originalEvent.target.files
Then, files is an array of File objects, containing name, lastModifiedDate, type etc.