Handling the selection of a file from a file input - javascript

I'm trying to have the filename of a chosen file appear in the body of a file picker. This is an Asp.Net Core view. I have the following file input:
<div class="form-group file-upload-wrapper">
<input id="the-file" type="file" name="name" onchange="handleFile()" />
<label class="custom-file-label" for="the-file">Choose a file</label>
</div>
I want the filename to appear in place of the Choose a file text.
My JS looks like this:
#section Scripts {
<script language="javascript">
function handleFile(file) {
console.log(file);
}
As it currently stands, I'm getting an error:
ReferenceError: handleFile is not defined
My assumption is that handleFile needs to look something like this:
document.getElementById("the-file").title = file.files[0].name;
Am I on the right lines with this, and why am I getting the above error?
JSFiddle here

You can use event handler for that. Remove onchange attribute form that element and use below:
document.getElementById('the-file')
.addEventListener('change', (e) => {
handleFile(e)
});
function handleFile(file) {
console.log(file.target.value);
}
Here is the snippet:
document.getElementById('the-file')
.addEventListener('change', (e) => {
handleFile(e)
});
function handleFile(file) {
console.log(file.target.value);
log(file.target.value);
}
function log(msg) {
document.getElementById('result').innerText = msg;
}
<div class="form-group file-upload-wrapper">
<input id="the-file" type="file" name="name" />
<label class="custom-file-label" for="the-file">Choose a file</label>
</div>
<pre id="result"></pre>

From the documentation , you need to modify the code like below:
<div class="custom-file">
<input type="file" class="custom-file-input" id="the-file" name="name"/>
<label class="custom-file-label" for="the-file">Choose a file</label>
</div>
#section Scripts
{
<script>
document.getElementById('the-file').addEventListener('change', function (e) {
var fileName = document.getElementById("the-file").files[0].name;
var nextSibling = e.target.nextElementSibling
nextSibling.innerText = fileName
});
</script>
}
You could refer to Bootstrap 4 File Input for more details.

why am I getting the above error?
The code within the fiddle is different from the OP. I'll take the code on Fiddle as an example.
First of all, note that you added a bootstrp.min.js reference, however, you didn't add a jquery for it. Because bootstrap.min.js has a dependency on jquery, it throws before the handleFile() function is defined.
That's why we could see an error of util.js:56 Uncaught TypeError: Cannot read property 'fn' of undefined at util.js:56 in the console. To fix that issue, either add a jquery.min.js before the bootstrap.min.js:
Or change the loading behavior of your js like:
And then you mix up the js statement with a function reference by :
<input id="the-file" type="file" name="name" onchange="this.handleFile" />
Note you should put a js statement instead of a single function reference within onchange="...". That being said, you could fix it by:
<input id="the-file" type="file" name="name" onchange="handleFile(event.target.files)" />
Your handleFile() uses a this that points to the window at runtime. As a result, it throws when invoked. Since we have passed the files as the arguments, change the function as below:
function handleFile(files) {
console.log(files);
}

<div class="form-group file-upload-wrapper">
<script>
const handleFile = file => {
console.log(file);
}
</script>
<input id="the-file" type="file" name="name" value ="file" onchange="handleFile(value)" />
<label class="custom-file-label" for="the-file">Choose a file</label>
</div>

Related

can't get input type number value [duplicate]

This question already has answers here:
Why does jQuery or a DOM method such as getElementById not find the element?
(6 answers)
Closed 1 year ago.
<div class="spacing">
<h5>Bill</h5>
<label for="bill"></label>
<input id="bill" type="number" name="bill" value="">
</div>
<script>
const bill = document.querySelector("#bill");
bill.addEventListener("input", function (e) {
console.log(bill.value);
})
</script>
i keep getting this error --
Uncaught TypeError: Cannot read property 'addEventListener' of null.
Try this. You are reading control before document is ready.
Solution 1
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function () {
const bill = document.getElementById("bill");
bill.addEventListener("input", function (e) {
console.log(bill.value);
})
});
</script>
Solution 2 Without JQuery
<script>
function printVal() {
const bill = document.getElementById("bill");
if (bill != null) {
bill.addEventListener("input", function (e) {
console.log(bill.value);
});
}
}
</script>
<div class="spacing">
<h5>Bill</h5>
<label for="bill"></label>
<input id="bill" type="number" name="bill" onkeypress="printVal();">
</div>
you have to convert it into integer
<script>
const bill = document.querySelector("#bill");
bill.addEventListener("input", function (e) {
var a = parseInt(bill.value);
console.log(bill.value);
console.log(typeof a);
})
</script>
The script tag should be after the html you want to apply the handler to, preferrably right before the closing body tag.
Another way to make this work is to use event delegation. The input handler is attached to the document. Detection of the input element is done within the handler function. In that case the script placement doesn't matter.
Example
<script>
document.addEventListener(`input`, evt => {
if (evt.target.id === `bill` && evt.target.value.trim().length) {
console.log(evt.target.value);}
});
</script>
<div class="spacing">
<h5>Bill</h5>
<label for="bill"></label>
<input id="bill" type="number" name="bill" value="">
</div>
This error might be some debugging issue as mentioned by Mr. Bravo in the comment. I am getting the output with same code you given.
const bill = document.querySelector("#bill");
bill.addEventListener("input", function(e) {
console.log(this.value); // You can use `this` keyword
});
<div class="spacing">
<h5>Bill</h5>
<label for="bill"></label>
<input id="bill" type="number" name="bill" value="">
</div>
But following code gives me error as you got Uncaught TypeError: Cannot read property 'addEventListener' of null
<script>
const bill = document.querySelector("#bill");
bill.addEventListener("input", function(e) {
console.log(this.value);
});
</script>
<div class="spacing">
<h5>Bill</h5>
<label for="bill"></label>
<input id="bill" type="number" name="bill" value="">
</div>
Either move your script to just before the </body> tag so you ensure that the DOM has loaded successfully before you try and access it, or use the DOMContentLoaded event to check to see if the DOM has loaded before performing any operations on it.
You should also reference the value of the target of the event you pass into the listener rather than bill.
window.addEventListener('DOMContentLoaded', () => {
const bill = document.querySelector("#bill");
bill.addEventListener('input', (e) => {
console.log(e.target.value);
});
});
<div class="spacing">
<h5>Bill</h5>
<label for="bill"></label>
<input id="bill" type="number" name="bill" value="">
</div>

Previewing multiple uploaded images individually

I have three image upload fields in my form. I am trying to preview the images before uploading. Till now i have been able to preview only one at a time. but i am trying to preview all of them simultaneously. Like
I am currently previewing like this.
function previewImages() {
var $preview = $('#preview').empty();
if (this.files) $.each(this.files, readAndPreview);
function readAndPreview(i, file) {
if (!/\.(jpe?g|png|gif)$/i.test(file.name)){
return alert(file.name +" is not an image");
} // else...
var reader = new FileReader();
$(reader).on("load", function() {
$preview.append($("<img/>", {src:this.result, height:500}));
});
reader.readAsDataURL(file);
}
}
$('#file-input').on("change", previewImages);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="form-group">
<label>Image 2</label>
<input id="file-input" type="file" multiple>
<div id="preview"></div>
</div>
<img id='img-upload'/>
</div>
<div class="form-group">
<label>Image 3</label>
<input id="file-input" type="file" multiple>
<div id="preview"></div>
</div>
You have some problems in your code.
Never use duplicate id's . That's the main reason your code works only for the first input type file. You use id='file-input' on all inputs. That's not correct HTML wise. Use classes instead or other html attributes.
You select the preview container but only the first one. $preview = $('#preview').empty(); where by writing $('#preview'), jquery finds the first item with id preview, selects it, empties it and then ignores all other divs with the same id. This is firstly because you don't select the corresponding preview div to the changed input file ( no connection between them in your var declaration ) and because again you use duplicate ( multiple ) id's in your HTML structure. Which will generate a lot of ' strange ' errors.
But even if you would use classes instead of id's ( class='preview' ) it won't exactly work because it will just select the first div with class preview and append all previews to that div.
So to make a connection between input and it's preview, use something like var $preview = $(this).next('.preview').empty(); . This way you know jQuery will select the next sibling with class preview of the changed input.
Alternatively ( if your HTML structure should change and preview is not exactly after the input ) you should use $(this).siblings('.preview').empty()
The most important thing you should learn from this answer is NOT to use same id`s on the page. And when you have multiple items with corresponding elements, select them accordingly.
function previewImages() {
const $preview = $(this).next('.preview').empty();
if (this.files) $.each(this.files, readAndPreview);
function readAndPreview(i, file) {
if (!/\.(jpe?g|png|gif)$/i.test(file.name)) {
return alert(file.name + " is not an image");
} // else...
const reader = new FileReader();
$(reader).on("load", function() {
$preview.append($("<img/>", {
src: this.result,
height: 100
}));
});
reader.readAsDataURL(file);
}
}
$('.file-input').on("change", previewImages);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="form-group">
<label>Image 1</label>
<input class="file-input" type="file" multiple>
<div class="preview"></div>
</div>
<img class='img-upload' />
<div class="form-group">
<label>Image 2</label>
<input class="file-input" type="file" multiple>
<div class="preview"></div>
</div>
<img class='img-upload' />
<div class="form-group">
<label>Image 3</label>
<input class="file-input" type="file" multiple>
<div class="preview"></div>
</div>
SIDE NOTE . You should use const and/or let instead of var when declaring variables.
var $preview=null;
function previewImages() {
$preview = $(this).next('#preview').empty();
if (this.files)
$.each(this.files,function(index,file){
readAndPreview(index,file);
});
}
function readAndPreview(i, file) {
if (!/\.(jpe?g|png|gif)$/i.test(file.name)){
return alert(file.name +" is not an image");
} // else...
var reader = new FileReader();
$(reader).on("load", function() {
$preview.append($("<img/>", {src:this.result, height:100}));
});
reader.readAsDataURL(file);
}
$('.file-input').on("change", previewImages);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="form-group">
<label>Image 2</label>
<input class="file-input" type="file" multiple>
<div id="preview"></div>
</div>
<img id='img-upload'/>
</div>
<div class="form-group">
<label>Image 3</label>
<input class="file-input" type="file" multiple>
<div id="preview"></div>
</div>
Try this. css ids are unique for a page. if you want to access multiple elements with same selector use class.

Uncaught ReferenceError: reg is not defined

Im trying to build a login and registration form using jquery, ajax and php. But im getting this error when im pressing the button for registration.
<!-- Formular for signing up -->
<form method="post">
<div class="form-group">
<label> Username </label>
<input type="text" class="form-control" name="newusername">
</div>
<div class="form-group">
<label> Password </label>
<input type="password" class="form-control" name="newpassword">
</div>
<div class="form-group">
<label> Your club </label>
<input type="text" class="form-control" name="newclub">
</div>
<button type="button" onClick='reg' class="btn btn-success">Sign up!</button>
</form>
And here is my script code
$(document).ready(function () {
// Function for registrate of new users
function reg(newusername, newpassword, newclub) {
$.post('class/callingClass.php', {
newusername: 'newusername',
newpassword: 'newpassword',
newclub: 'newclub'
});
};
});
Functions called from onXYZ attribute event handlers must be globals (it's one of the several reasons not to use them). Your reg function isn't a global, it's nicely contained within your ready callback (which is a Good Thing™, the global namespace is already really crowded and prone to conflicts).
Separately, onClick='reg' wouldn't work, it would have to be onClick='reg()'.
Instead, hook reg up dynamically via on:
<button type="button" id="btn-reg" class="btn btn-success">Sign up!</button>
<!-- Removed onClick, added id -->
and
$(document).ready(function () {
$("#btn-reg").on("click", reg); // <== Added
// Function for registrate of new users
function reg(newusername, newpassword, newclub) {
$.post('class/callingClass.php', {
newusername: 'newusername',
newpassword: 'newpassword',
newclub: 'newclub'
});
};
});
I've used an id above, but it doesn't have to be an id, that's just one way to look up the element. Any CSS selector that would find it would be fine.
Use onClick='reg()'. You need to do the function call here, which is the proper syntax.
Update : You also need to move your function outside of the $(document).ready(function(){}).

Uncaught Type Error: Cannot read property, JS executing before page renders

I am receiving the following error in my console:
Uncaught TypeError: Cannot read property ‘value’ of null
What I'm attempting to do is copy text input from one input box into another, when you click the checkbox the value of one input will be copied into another input.
HTML
<input name="stry" type="text" id="stry"/>
<input type="checkbox" name="sendsms" onclick="CopyStory(this.form)">
<div id="container">
<input type="text" class="form-control" name="body">
</div>
JS
function CopyStory(f) {
if(f.sendsms.checked == true) {
f.stry.value = f.body.value;
}
}
I believe the problem is that the code is executed before the elements load because I have a javascript alert modal pop-up which prevents the page from loading unless you press 'Ok'
Alert JS
$('#container').fadeOut('fast').delay(7000).fadeIn('fast');
alert("This page is loading....");
I've tried wrapping it around document.ready(function blah... but then it gives me an error that: " 'CopyStory' is not defined".
Any suggestions?
Take a look at this JSFiddle.
JS
function copyStory(ch) {
if(ch.checked)
var text1 = document.getElementById("stry").value;
else
text1='';
document.getElementById("second").value = text1;
}
$('#container').fadeOut('fast').delay(7000).fadeIn('fast');
alert("This page is loading....");
HTML
<input name="stry" type="text" id="stry"/>
<input type="checkbox" name="sendsms" onclick="copyStory(this)">
<input type="text" class="form-control" id="second" name="body">
<div id="container">
</div>
You are not using the form tags and trying to access a form..!
Try this,
function CopyStory(f) {
if(f.sendsms.checked == true) {
console.log(f.body.value);
f.stry.value = f.body.value;
}
}
<div>
<form>
<input name="stry" type="text" id="stry"/>
<input type="checkbox" name="sendsms" onclick="CopyStory(this.form)">
<div id="container">
<input type="text" class="form-control" name="body">
</form>
</div>
Just put the js script inside <head></head>
First, wrap your code in $(function(){ //code here }); to execute your js after page loads.
About 'CopyStory' is not defined:
when you define function like:
$(function(){
function CopyStory(){ //... }
});
CopyStory is not visible in global scope, so if you want to fix your problem just change defenition to:
$(function(){
window.CopyStory = function(){ //... }
});
p.s. assign a variable to window propery is the only way to define global variable inside a local scope.

Can't target input[type=file] with multiple forms on page with javascript

I have several dynamic forms on a page that each have a file input... How do I do I target the correct file input using $(this) in javascript?
Here is my form
<form enctype="multipart/form-data" action="category_manage.php" method="post">
<div class="plus-button-container">
<input id="upfile" name="photo" type="file" onchange="submitFormAfterImageCheck();"/>
</div>
<input type="hidden" name="sml_image" value="sml_image" />
</form>
And here is my javascript function
function submitFormAfterImageCheck() {
var formSubmit = $(this).closest("form");
var file = $(this).closest('input[type=file]').val();
alert(file);
}
//gives me undefined
I also tried this that works, but only for the first form ...
function submitFormAfterImageCheck() {
var formSubmit = $(this).closest("form");
var file = $('input[type=file]').val();
alert(file);
}
I think I need something like this, but this gives me undefined
var file = $(this).find('input[type=file]').val();
Since you have an inlined event handler, inside the event handler this does not refer to the changed element.
One easy solution is to pass the changed element as an parameter to the event handler like
<input id="upfile" name="photo" type="file" onchange="submitFormAfterImageCheck(this);"/>
then
function submitFormAfterImageCheck(el) {
var formSubmit = $(el).closest("form");
var file = $(el).val();
alert(file);
}
Note: Since you are using jQuery it is better to use jQuery based event handlers instead of inlined ones
The way you have it submitFormAfterImageCheck is executing with the global object(window) as this.
I'd suggest separating code logic from the markup with jQuery event handlers.
<form enctype="multipart/form-data" action="category_manage.php" method="post">
<div class="plus-button-container">
<input id="upfile" name="photo" type="file" onchange="submitFormAfterImageCheck();"/>
</div>
<input type="hidden" name="sml_image" value="sml_image" />
</form>
<script>
function submitFormAfterImageCheck() {
var formSubmit = $(this).closest("form");
var file = $(this).val();
alert(file);
}
$('input[type="file"]').on('change', submitFormAfterImageCheck);
</script>
<input id="upfile" name="photo" type="file" onchange="submitFormAfterImageCheck(this);"/>
and :
function submitFormAfterImageCheck(source) {
alert($(source).val());
}

Categories