ng-model not updating with input type=”file”

Loading

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 correct Content-Type.

Leave a Reply

Your email address will not be published. Required fields are marked *