By default, AngularJS does not support two-way data binding for <input type="file">
using ng-model
. This is because file inputs do not store values as text like other form fields (e.g., text inputs). Instead, they store FileList objects, which AngularJS cannot automatically track through ng-model
.
Step 1: Understanding Why ng-model
Doesn’t Work with File Inputs
Incorrect Approach:
<input type="file" ng-model="myFile">
<p>Selected File: {{ myFile }}</p> <!-- This will not work -->
Why does this fail?
ng-model
works by binding form fields to AngularJS scope properties, but file inputs don’t store values as normal strings.- The browser does not allow JavaScript to read file paths directly due to security restrictions.
Step 2: Correct Approach – Using ng-change
& ngf-select
(AngularJS File Upload)
Method 1: Use ng-change
to Capture File Data Manually
Instead of ng-model
, use ng-change
and a custom function to store the selected file in $scope
.
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AngularJS File Upload Fix</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body ng-controller="myController">
<h3>Select a File:</h3>
<input type="file" id="fileInput" onchange="angular.element(this).scope().uploadFile(this.files)">
<h4>Selected File: {{ selectedFile.name }}</h4>
<h4>File Size: {{ selectedFile.size }} bytes</h4>
<script>
var app = angular.module("myApp", []);
app.controller("myController", function ($scope) {
$scope.selectedFile = {};
$scope.uploadFile = function (files) {
if (files.length > 0) {
$scope.selectedFile = files[0]; // Store file in scope
$scope.$apply(); // Trigger AngularJS digest cycle
}
};
});
</script>
</body>
</html>
Why This Works?
- Uses
onchange="angular.element(this).scope().uploadFile(this.files)"
to manually detect file selection. - Calls
uploadFile(files)
, which updates$scope.selectedFile
with the selected file object. - Uses
$scope.$apply()
to manually trigger AngularJS digest cycle, ensuring the UI updates.
Method 2: Use ngf-select
(With ng-file-upload
Library)
If you’re using ng-file-upload
, a popular AngularJS module for file handling, use ngf-select
instead of ng-model
.
1️⃣ Install ng-file-upload
<script src="https://cdnjs.cloudflare.com/ajax/libs/ng-file-upload/12.2.13/ng-file-upload.min.js"></script>
2️⃣ Modify HTML Code
<input type="file" ngf-select ng-model="myFile" name="file" accept="image/*">
<p>Selected File: {{ myFile.name }}</p>
Why This Works?
ngf-select
is specifically designed to bind file inputs with AngularJS models.- It allows two-way binding for files like
ng-model
.
Step 3: Handling File Upload with AngularJS $http
Once you’ve captured the file, you may want to upload it to a server. You can use AngularJS $http
service to send the file as FormData
.
Example: File Upload Using $http
<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AngularJS File Upload</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body ng-controller="myController">
<h3>Upload File:</h3>
<input type="file" id="fileInput" onchange="angular.element(this).scope().uploadFile(this.files)">
<button ng-click="submitFile()">Upload</button>
<h4>Selected File: {{ selectedFile.name }}</h4>
<script>
var app = angular.module("myApp", []);
app.controller("myController", function ($scope, $http) {
$scope.selectedFile = {};
$scope.uploadFile = function (files) {
if (files.length > 0) {
$scope.selectedFile = files[0];
$scope.$apply();
}
};
$scope.submitFile = function () {
var formData = new FormData();
formData.append("file", $scope.selectedFile);
$http.post("your-upload-url-here", formData, {
headers: { "Content-Type": undefined }, // Let browser set the content type
transformRequest: angular.identity
}).then(function (response) {
alert("File uploaded successfully!");
}).catch(function (error) {
alert("File upload failed.");
});
};
});
</script>
</body>
</html>
Why This Works?
- Uses
FormData
to append the file. - Uses
$http.post()
to send the file to the server. headers: { "Content-Type": undefined }
allows AngularJS to set the correctContent-Type
.