如何在Angular上的文件输入上触发'click'事件?

时间:2022-04-22 23:59:47

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:

JS:

$scope.click = ->
    # $('#save-csv').trigger('click')

Error I get:

我得到的错误:

Error: $apply already in progress

3 个解决方案

#1


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函数以触发setTimeout中的输入单击。这允许第一个$ apply完成,然后将触发另一个。

$scope.click = function() {
    setTimeout(function() {
        inputEl.click();
    }, 0);
}

Note that I use setTimeout, not $timeout. $timeout would also be inside an $apply block.

请注意,我使用setTimeout,而不是$ timeout。 $ timeout也在$ apply块内。

#2


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.

想法是使用按钮来“模拟”文件输入;我使用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)") 

#3


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.

我刚刚遇到了这个问题并写了一个解决方案。您可以编写由容器,按钮和类型为file的input元素组成的自定义指令。使用CSS,然后将输入放在自定义按钮上,但不透明度为0.您可以将容器的高度和宽度设置为按钮的偏移宽度和高度,输入的高度和宽度设置为容器的100%。

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

如果你使用html,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

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

#1


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函数以触发setTimeout中的输入单击。这允许第一个$ apply完成,然后将触发另一个。

$scope.click = function() {
    setTimeout(function() {
        inputEl.click();
    }, 0);
}

Note that I use setTimeout, not $timeout. $timeout would also be inside an $apply block.

请注意,我使用setTimeout,而不是$ timeout。 $ timeout也在$ apply块内。

#2


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.

想法是使用按钮来“模拟”文件输入;我使用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)") 

#3


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.

我刚刚遇到了这个问题并写了一个解决方案。您可以编写由容器,按钮和类型为file的input元素组成的自定义指令。使用CSS,然后将输入放在自定义按钮上,但不透明度为0.您可以将容器的高度和宽度设置为按钮的偏移宽度和高度,输入的高度和宽度设置为容器的100%。

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

如果你使用html,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

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