2013-05-19 27 views
24

Tôi muốn nhận một tập tin với AngularJS:file chọn với góc JS

HTML:

<div ng-controller="TopMenuCtrl"> 
    <button class="btn" ng-click="isCollapsed = !isCollapsed">Toggle collapse</button> 
    <input type="file" ng-model="filepick" ng-change="pickimg()" multiple /> 
    <output id="list"></output> 
</div> 

javascript:

angular.module('plunker', ['ui.bootstrap']); 
function TopMenuCtrl($scope) { 
    $scope.pickimg = function() { 
     alert('a'); 
    }; 
} 

Làm thế nào tôi có thể ràng buộc các tập tin đầu vào onchange hành động trên chức năng AngularJS pickimg? Và làm thế nào tôi có thể thao tác các tệp được tải lên sau?

Trả lời

48

Góc chưa hỗ trợ ng-thay đổi cho đầu vào [type = file] vì vậy bạn phải tự mình thực hiện thay đổi.

Đầu tiên, trong HTML, định nghĩa Javascript cho onchange như sau:

<input ng-model="photo" 
     onchange="angular.element(this).scope().file_changed(this)" 
     type="file" accept="image/*" /> 

Và sau đó trong mã điều khiển góc của bạn, xác định các chức năng:

$scope.file_changed = function(element) { 

    $scope.$apply(function(scope) { 
     var photofile = element.files[0]; 
     var reader = new FileReader(); 
     reader.onload = function(e) { 
      // handle onload 
     }; 
     reader.readAsDataURL(photofile); 
    }); 
}; 
+2

Tôi đã sử dụng kỹ thuật tương tự này thành công. Thật xấu xí ... nhưng đó là điều tốt nhất chúng tôi có bây giờ. – Espilon

+0

Điều gì xảy ra với ...? – user1876508

+0

@ user1876508 "Sau khi bạn đã nhận được tham chiếu tệp, hãy khởi tạo đối tượng FileReader để đọc nội dung của nó trong bộ nhớ. Khi tải xong, sự kiện tải của người đọc được kích hoạt và thuộc tính kết quả của nó có thể được sử dụng để truy cập dữ liệu tệp." Từ http://www.html5rocks.com/en/tutorials/file/dndfiles/ –

6

giải pháp Teemu sẽ không làm việc cho IE9 .

Tôi đã đặt cùng một chỉ thị góc đơn giản với Flash polyfill cho các trình duyệt không hỗ trợ HTML5 FormData, bạn cũng có thể nghe sự kiện tải lên tiến trình.

https://github.com/danialfarid/ng-file-upload Demo: http://angular-file-upload.appspot.com/

<script src="angular.min.js"></script> 
<script src="ng-file-upload.js"></script> 

<div ng-controller="MyCtrl"> 
    <input type="text" ng-model="additionalData"> 
    <div ngf-select ng-model="files" > 
</div> 

điều khiển:

Upload.upload({ 
    url: 'my/upload/url', 
    data: additionalData, 
    file: files 
    }).then(success, error, progress); 
+1

Đây là cách tiếp cận toàn diện hơn. – Aviro

17

tôi đã sử dụng phương pháp nêu trên cố gắng để tải một hình ảnh xem trước khi tập tin mới được chọn, tuy nhiên nó làm việc khi tôi thử nó như rằng:

$scope.file_changed = function(element, $scope) { 

    $scope.$apply(function(scope) { 
     var photofile = element.files[0]; 
     var reader = new FileReader(); 
     reader.onload = function(e) { 
      $scope.prev_img = e.target.result; 
     }; 
     reader.readAsDataURL(photofile); 
    }); 
}); 

Tôi đào nhiều hơn vào nó và thấy rằng phạm vi $. $ Áp dụng nên được bên trong reader.onLoad nếu không thay đổi một biến $ phạm vi sẽ không làm việc, vì vậy tôi đã làm như sau và nó đã làm việc:

$scope.file_changed = function(element) { 

     var photofile = element.files[0]; 
     var reader = new FileReader(); 
     reader.onload = function(e) { 
      $scope.$apply(function() { 
       $scope.prev_img = e.target.result; 
      }); 
     }; 
     reader.readAsDataURL(photofile); 
}; 
+1

Xem trước hình ảnh trong chế độ xem bằng cách thêm: Lars

+0

Mã đã thay đổi là những gì thực sự cần thiết, chỉ mới bắt đầu tự hỏi tại sao mô hình của tôi không cập nhật. –

2

Đây là một trọng lượng nhẹ chỉ thị tôi đã viết để giải quyết vấn đề này, phản ánh cách thức gắn kết các sự kiện góc cạnh.

Bạn có thể sử dụng các chỉ thị như thế này:

HTML

<input type="file" file-change="yourHandler($event, files)" /> 

Như bạn thấy, bạn có thể tiêm các file được chọn vào xử lý sự kiện của bạn, như bạn sẽ bơm một $ sự kiện đối tượng vào bất kỳ trình xử lý sự kiện nào.

Javascript

angular 
    .module('yourModule') 
    .directive('fileChange', ['$parse', function($parse) { 

    return { 
     require: 'ngModel', 
     restrict: 'A', 
     link: function ($scope, element, attrs, ngModel) { 

     // Get the function provided in the file-change attribute. 
     // Note the attribute has become an angular expression, 
     // which is what we are parsing. The provided handler is 
     // wrapped up in an outer function (attrHandler) - we'll 
     // call the provided event handler inside the handler() 
     // function below. 
     var attrHandler = $parse(attrs['fileChange']); 

     // This is a wrapper handler which will be attached to the 
     // HTML change event. 
     var handler = function (e) { 

      $scope.$apply(function() { 

      // Execute the provided handler in the directive's scope. 
      // The files variable will be available for consumption 
      // by the event handler. 
      attrHandler($scope, { $event: e, files: e.target.files }); 
      }); 
     }; 

     // Attach the handler to the HTML change event 
     element[0].addEventListener('change', handler, false); 
     } 
    }; 
    }]); 
+2

html gotta sử dụng ngModel mặc dù.' ' – mayankcpdixit

3

Sau đây là cách tiếp cận của tôi với một chỉ thị.

Chỉ

angular 
    .module('yourModule') 
    .directive('fileChange', function() { 
    return { 
    restrict: 'A', 
    scope: { 
     handler: '&' 
    }, 
    link: function (scope, element) { 
     element.on('change', function (event) { 
     scope.$apply(function(){ 
      scope.handler({files: event.target.files}); 
     }); 
     }); 
    } 
    }; 
}); 

HTML

<input type="file" file-change handler="fileSelect(files)"> 

khiển

fileSelect = function (files) { 
     var file = files[0]; 
     //you will get the file object here 
} 
0

Tôi đã thực hiện một chỉ thị. Đây là số fiddle.
Ứng dụng hoạt động để chọn csv và hiển thị chúng dưới dạng bảng html.
Với chỉ thị thay đổi trên tệp, bạn có thể xác định việc đọc và phân tích tệp (với các dịch vụ, có thể là) logic trong bộ điều khiển chính nó sẽ cung cấp sự linh hoạt hơn. Chỉ cần lưu ý, hàm ac.onFileChange được truyền cho thuộc tính thay đổi tệp sẽ trở thành trình xử lý cho sự kiện thay đổi đầu vào bên trong chỉ thị.

(function (angular, document) { 
 

 
    angular 
 
     .module("app.directives", []) 
 
     .directive("onFileChange", ["$parse", function ($parse) { 
 
     return { 
 
      restrict: "A", 
 
      link: function (scope, ele, attrs) { 
 
       // onFileChange is a reference to the same function which you would define 
 
       // in the controller. So that you can keep your logic in the controller. 
 
       var onFileChange = $parse(attrs.onFileChange.split(/\(/)[0])(scope) 
 
       ele.on("change", onFileChange) 
 
       ele.removeAttr("on-file-change") 
 
      } 
 
     } 
 
     }]) 
 

 
    angular 
 
     .module("app.services", []) 
 
     .service("Parse", ["$q", function ($q) { 
 
     var Parse = this 
 
     Parse.csvAsGrid = function (file) { 
 
      return $q(function (resolve, reject) { 
 
       try { 
 
        Papa.parse(file, { 
 
        complete: function (results) { 
 
         resolve(results.data) 
 
        } 
 
        }) 
 
       } catch (e) { 
 
        reject(e) 
 
       } 
 
      }) 
 
     } 
 
     }]) 
 

 
    angular 
 
     .module("app", ["app.directives", "app.services"]) 
 
     .controller("appCtrl", ["$scope", "Parse", function ($scope, Parse) { 
 
     var ac = this 
 
     ac.fileName = "" 
 
     ac.onFileChange = function (event) { 
 
      if (!event.target.files.length) { 
 
       return 
 
      } 
 
      Parse.csvAsGrid(event.target.files[0]).then(outputAsTable) 
 
     } 
 

 
     ac.clearInput = function (event) { 
 
      var input = angular.element(event.target) 
 
      input.val("") 
 
      document.getElementById("output").innerHTML = "" 
 
     } 
 

 
     function outputAsTable(grid) { 
 
      var table = ['<table border="1">'] 
 
      grid.map(function (row) { 
 
       table.push('<tr>') 
 
       row.map(function (cell) { 
 
        table.push('<td>' + cell.replace(/["']/g, "") + '</td>') 
 
       }) 
 
       table.push('</tr>') 
 
      }) 
 
      table.push('</table>') 
 
      document.getElementById("output").innerHTML = table.join("\n") 
 
     } 
 
     }]) 
 

 
})(angular, document)
table { 
 
    border-collapse: collapse; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script> 
 
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/4.1.2/papaparse.min.js"></script> 
 

 
<div ng-app="app" ng-controller="appCtrl as ac"> 
 
    <label>Select a comma delimited CSV file:-</label> 
 
    <input id="filePicker" type="file" on-file-change="ac.onFileChange(event)" ng-click="ac.clearInput($event)"/>{{ac.fileName}} 
 
</div> 
 
<div id="output"></div>

2

Sử dụng Madura's answer từ trên cao, đây là dòng chảy hoàn chỉnh cho đọc một tệp JSON địa phương:

Tạo chỉ:

angular 
    .module('app.services') 
    .directive('fileChange', function() { 
    return { 
    restrict: 'A', 
    scope: { 
     handler: '&' 
    }, 
    link: function (scope, element) { 
     element.on('change', function (event) { 
     scope.$apply(function(){ 
      scope.handler({files: event.target.files}); 
     }); 
     }); 
    } 
    }; 
}); 

HTML:

<input type="file" file-change handler="fileSelect(files)"> 

Javascript:

$scope.fileSelect = function(files) { 
    var file = files[0]; 
    var reader = new FileReader(); 
    reader.onload = function(e) { 
    console.log("on load", e.target.result); 
    } 
    reader.readAsText(file); 
} 
+0

Khi tôi thử nó, nó sẽ không bị ngắt trong 'this.fileSelect() '. Khi tôi thay đổi nó thành '$ scope.fileSelect()', nó có breakpoint, nhưng chỉ báo cáo tên của tệp, không phải là một đường dẫn đầy đủ. Bạn có thể giúp? Có rất nhiều ví dụ chọn tập tin AngulrJs phức tạp fiendishly ra khỏi đó, và đây là một trong những chỉ có vẻ đơn giản, đủ để grok. Rất gần, và ... – Mawg

+1

Bạn nói đúng, nó phải là $ scope chứ không phải 'this'. Theo như đường dẫn tập tin, tôi nghĩ rằng hành vi bạn đang nhìn thấy là hành vi chính xác. Bạn vẫn có thể đọc tệp dựa trên kết quả bạn nhận được. – Snowman

+0

Điều này phù hợp với tôi và là triển khai đơn giản nhất mà tôi đã tìm thấy cho đến nay. – Mawg

Các vấn đề liên quan