使用<input type =“file”/>时为什么Angular绑定失败?

时间:2015-05-13 18:25:13

标签: javascript angularjs angularjs-scope

我远不是Angular的专家,所以我必须尝试在这里提问。我已经添加了在AngularJS项目中上传文件的可能性。我需要在用户提交表单之前在文本框(或最好是只读字段)中显示所选文件名。它包含许多需要验证的字段。问题是,所选的文件名永远不会出现。选择文件后,文本块仍为空。我尝试过以下代码(Plunker:http://plnkr.co/edit/Ll3GZdpp8Tsqwvo0W1ax):

的index.html:

<!DOCTYPE html>
<html ng-app="myApp">

<head lang="en">
  <meta charset="utf-8" />
  <title>Custom Plunker</title>
  <script data-require="jquery@2.1.3" data-semver="2.1.3" src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
  <link data-require="bootstrap@*" data-semver="3.3.2" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" />
  <script data-require="bootstrap@*" data-semver="3.3.2" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
  <link rel="stylesheet" type="text/css" href="http://angular-ui.github.com/ng-grid/css/ng-grid.css" />
  <link rel="stylesheet" type="text/css" href="style.css" />
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.min.js"></script>
  <script type="text/javascript" src="http://angular-ui.github.com/ng-grid/lib/ng-grid.debug.js"></script>
  <script type="text/javascript" src="main.js"></script>
</head>

<body ng-controller="MyCtrl">

  <div class="row">
    <div class="col-md-12">
      <span class="btn btn-default btn-file">
              Välj fil... <input type="file" onchange=" angular.element(this).scope().setFile(this) ">
                                        </span>
      <input type="text" ng-model="organizationSettings.logotypeFileName" />
    </div>
  </div>
</body>

</html>

app.js:

var app = angular.module('myApp', []);
app.controller('MyCtrl', function($scope) {
  $scope.organizationSettings = {};

  $scope.setFile = function(element) {
    $scope.fileToUpload = element.files[0];
    console.log($scope.fileToUpload.name);
    $scope.organizationSettings.logotypeFileName = $scope.fileToUpload.name;
  };    
});

的CSS:

.btn-file {
    position: relative;
    overflow: hidden;
}
.btn-file input[type=file] {
    position: absolute;
    top: 0;
    right: 0;
    min-width: 100%;
    min-height: 100%;
    font-size: 100px;
    text-align: right;
    filter: alpha(opacity=0);
    opacity: 0;
    outline: none;
    background: white;
    cursor: inherit;
    display: block;
}

3 个答案:

答案 0 :(得分:2)

原因是你正在使用onchange,这是任何角度指令之外的事件。

每当您使用角度超出更改范围的事件时,您需要通知使用$apply

更新该范围管理的视图部分需要摘要

最简单的解决方法是使用ng-change而不是原生onchange。所有角度事件处理指令都将在内部触发$apply

替代方案(不是最好的方法)是保持改变并做:

$scope.setFile = function(element) {  
    $scope.fileToUpload = element.files[0];
    console.log($scope.fileToUpload.name);
    $scope.organizationSettings.logotypeFileName = $scope.fileToUpload.name;

    $scope.$apply();
}; 

答案 1 :(得分:1)

我认为绑定更改可以更轻松,我将在下面解释如何执行此操作。通过将ng-model设置为输入,它将自动将输入控件绑定到控制器范围中定义的变量。因此,如果指定新文件,它将自动更新模型$ scope.fileToUpload。反过来说:在JS中完成的$ scope.fileToUpload中的任何更改都将反映在DOM中。

index.html - 尝试替换

<input type="file" onchange=" angular.element(this).scope().setFile(this) ">

<input type="file" ng-model="fileToUpload">

在app.js中,你可以摆脱:

$scope.setFile = function(element) {
    $scope.fileToUpload = element.files[0];
    console.log($scope.fileToUpload.name);
    $scope.organizationSettings.logotypeFileName = $scope.fileToUpload.name;
  };    

答案 2 :(得分:1)

您无法使用ng-change进行文件上传,因为angularjs中的文件上传不支持绑定,这是angularjs中的一个问题。

在其他情况下,当您使用ng-change(文件上传除外)时,您必须使用ng-model使ng-change指令工作,以便根据它触发更改(所以只有你在使用它时会得到"Error: No controller: ngModel"

最好的解决方案是手动触发$scope.$apply()以便以编程方式设置它来绑定输入模型。