I'm trying to trigger the click event of the <input type="file">
element from the button
.
<input id="upload"
type="file"
ng-file-select="onFileSelect($files)"
style="display: none;">
<button type="button"
ng-click="angular.element('#upload').trigger('click');">Upload</button>
It's common practice to hide the uglified beast known as <input type=file>
and trigger it's click event by some other means.
This question is related to
angularjs
I took the answer posted by Osiloke (Which was the easiest and most complete imho) and I added a change event listener. Works great! Thanks Osiloke. See below if you are interested:
HTML:
<div file-button>
<button class='btn btn-success btn-large'>Select your awesome file</button>
</div>
Directive:
app.directive('fileButton', function() {
return {
link: function(scope, element, attributes) {
var el = angular.element(element)
var button = el.children()[0]
el.css({
position: 'relative',
overflow: 'hidden',
width: button.offsetWidth,
height: button.offsetHeight
})
var fileInput = angular.element('<input id='+scope.file_button_id+' type="file" multiple />')
fileInput.css({
position: 'absolute',
top: 0,
left: 0,
'z-index': '2',
width: '100%',
height: '100%',
opacity: '0',
cursor: 'pointer'
})
el.append(fileInput)
document.getElementById(scope.file_button_id).addEventListener('change', scope.file_button_open, false);
}
}
});
Controller:
$scope.file_button_id = "wo_files";
$scope.file_button_open = function()
{
alert("Files are ready!");
}
Simply have them in the same controller, and do something like this:
HTML:
<input id="upload"
type="file"
ng-file-select="onFileSelect($files)"
style="display: none;">
<button type="button"
ng-click="startUpload()">Upload</button>
JS:
var MyCtrl = [ '$scope', '$upload', function($scope, $upload) {
$scope.files = [];
$scope.startUpload = function(){
for (var i = 0; i < $scope.files.length; i++) {
$upload($scope.files[i]);
}
}
$scope.onFileSelect = function($files) {
$scope.files = $files;
};
}];
This is, in my opinion, the best way to do it in angular. Using jQuery to find the element and trigger an event isn't the best practice.
best and simple way to use native java Script which is one liner code.
document.querySelector('#id').click();
Just add 'id' to your html element like
<button id="myId1" ng-click="someFunction()"></button>
check condition in javascript code
if(condition) {
document.querySelector('#myId1').click();
}
The solution, as pointed out by other answers, is to use
angular.element(element).trigger(event);
Here's an example of how I randomly select multiple select
elements:
$scope.randomize = function(){
var games = [].slice.call(document.querySelectorAll('.games select'));
games.forEach(function(e){
// Logically change the element (Angular won't know about this)
e.selectedIndex = parseInt(Math.random() * 100, 10) < 50 ? 1 : 2;
// Manually tell Angular that the DOM has changed
angular.element(e).trigger('change');
});
};
I just came across this problem and have written a solution for those of you who are using Angular. You can write a custom directive composed of a container, a button, and an input element with type file. With CSS you then place the input over the custom button but with opacity 0. You set the containers height and width to exactly the offset width and height of the button and the input's height and width to 100% of the container.
the directive
angular.module('myCoolApp')
.directive('fileButton', function () {
return {
templateUrl: 'components/directives/fileButton/fileButton.html',
restrict: 'E',
link: function (scope, element, attributes) {
var container = angular.element('.file-upload-container');
var button = angular.element('.file-upload-button');
container.css({
position: 'relative',
overflow: 'hidden',
width: button.offsetWidth,
height: button.offsetHeight
})
}
};
});
a jade template if you are using jade
div(class="file-upload-container")
button(class="file-upload-button") +
input#file-upload(class="file-upload-input", type='file', onchange="doSomethingWhenFileIsSelected()")
the same template in html if you are using html
<div class="file-upload-container">
<button class="file-upload-button"></button>
<input class="file-upload-input" id="file-upload" type="file" onchange="doSomethingWhenFileIsSelected()" />
</div>
the css
.file-upload-button {
margin-top: 40px;
padding: 30px;
border: 1px solid black;
height: 100px;
width: 100px;
background: transparent;
font-size: 66px;
padding-top: 0px;
border-radius: 5px;
border: 2px solid rgb(255, 228, 0);
color: rgb(255, 228, 0);
}
.file-upload-input {
position: absolute;
top: 0;
left: 0;
z-index: 2;
width: 100%;
height: 100%;
opacity: 0;
cursor: pointer;
}
One more directive
html
<btn-file-selector/>
code
.directive('btnFileSelector',[function(){
return {
restrict: 'AE',
template: '<div></div>',
link: function(s,e,a){
var el = angular.element(e);
var button = angular.element('<button type="button" class="btn btn-default btn-upload">Add File</button>');
var fileForm = angular.element('<input type="file" style="display:none;"/>');
fileForm.on('change', function(){
// Actions after the file is selected
console.log( fileForm[0].files[0].name );
});
button.bind('click',function(){
fileForm.click();
});
el.append(fileForm);
el.append(button);
}
}
}]);
So it was a simple fix. Just had to move the ng-click
to a scope click handler:
<input id="upload"
type="file"
ng-file-select="onFileSelect($files)"
style="display: none;">
<button type="button"
ng-click="clickUpload()">Upload</button>
$scope.clickUpload = function(){
angular.element('#upload').trigger('click');
};
for jqLite just use triggerHandler with event name, To simulate a "click" try:
angular.element("tr").triggerHandler("click");
_x000D_
If you are getting $scope binding errors make sure you wrap the click event code on a setTimeout Function.
VIEW
<input id="upload"
type="file"
ng-file-select="onFileSelect($files)"
style="display: none;">
<button type="button"
ng-click="clickUpload()">Upload</button>
CONTROLLER
$scope.clickUpload = function(){
setTimeout(function () {
angular.element('#upload').trigger('click');
}, 0);
};
I think you are over complicated things a bit. Do you really need to trigger a click on the input from your button ?
I suggest you just apply a proper style to your input and the ngFileSelect directive will do the rest and call your onFileSelect function whenever a file is submitted :
input.file {
cursor: pointer;
direction: ltr;
font-size: 23px;
margin: 0;
opacity: 0;
position: absolute;
right: 0;
top: 0;
transform: translate(-300px, 0px) scale(4);
}
I had this same issue and this fiddle is the shizzle :) It uses a directive to properly style the file field and you can even make it an image or whatever.
http://jsfiddle.net/stereosteve/v5Rdc/7/
/*globals angular:true*/_x000D_
var buttonApp = angular.module('buttonApp', [])_x000D_
_x000D_
buttonApp.directive('fileButton', function() {_x000D_
return {_x000D_
link: function(scope, element, attributes) {_x000D_
_x000D_
var el = angular.element(element)_x000D_
var button = el.children()[0]_x000D_
_x000D_
el.css({_x000D_
position: 'relative',_x000D_
overflow: 'hidden',_x000D_
width: button.offsetWidth,_x000D_
height: button.offsetHeight_x000D_
})_x000D_
_x000D_
var fileInput = angular.element('<input type="file" multiple />')_x000D_
fileInput.css({_x000D_
position: 'absolute',_x000D_
top: 0,_x000D_
left: 0,_x000D_
'z-index': '2',_x000D_
width: '100%',_x000D_
height: '100%',_x000D_
opacity: '0',_x000D_
cursor: 'pointer'_x000D_
})_x000D_
_x000D_
el.append(fileInput)_x000D_
_x000D_
_x000D_
}_x000D_
}_x000D_
})
_x000D_
<div ng-app="buttonApp">_x000D_
_x000D_
<div file-button>_x000D_
<button class='btn btn-success btn-large'>Select your awesome file</button>_x000D_
</div>_x000D_
_x000D_
<div file-button>_x000D_
<img src='https://www.google.com/images/srpr/logo3w.png' />_x000D_
</div>_x000D_
_x000D_
</div>
_x000D_
Source: Stackoverflow.com