Reputation: 7563
here is the view in jade
:
button#save-csv-btn(ng-click="click()") Export CSV
input#save-csv(style="display:none", type="file", onchange="angular.element(this).scope().saveCSVFileChanged(this)")
js:
$scope.click = ->
# $('#save-csv').trigger('click')
Error I get:
Error: $apply already in progress
Upvotes: 8
Views: 12950
Reputation: 1734
I just came across this problem and have written a drop in solution. 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;
}
Upvotes: 1
Reputation: 7563
The idea was to use button to 'emulate' the file input; I achieved this using http://gregpike.net/demos/bootstrap-file-input/demo.html.
input#save-csv(type="file", title="Export to CSV", onchange="angular.element(this).scope().saveCSVFileChanged(this)")
Upvotes: 3
Reputation: 7975
I changed $scope.click
function to trigger the input click in a setTimeout
. This lets the first $apply
finish, and then will trigger another one.
$scope.click = function() {
setTimeout(function() {
inputEl.click();
}, 0);
}
Note that I use setTimeout
, not $timeout
. $timeout
would also be inside an $apply
block.
Upvotes: 11