8

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
3
  • You probably want to include the actual javascript here and the output from jade instead of the pre-processed code since more people will be able to help. Generally this means you called $scope.$apply() within a function that is triggered during a $scope.$apply() Commented Aug 22, 2013 at 0:56
  • Also this seems generally like a bad idea, although you're not manipulating the DOM even assuming some element is there by name without using directives as your means to encapsulate that logic is not good. Commented Aug 22, 2013 at 1:12
  • This is quite a standard way of having a styled file input, by hiding the actual <input> and triggering click on it from another method. the problem is that angular throws an error because it does an apply within an apply Commented Oct 22, 2013 at 13:14

3 Answers 3

11

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.

Sign up to request clarification or add additional context in comments.

1 Comment

I had the same issue as OP, and using $timeout instead of setTimeout worked for me as well
3

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)") 

Comments

1

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;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.