ManxJason
ManxJason

Reputation: 940

Apply ng-change to an <input type="file"..>, that already uses it's own Directive

I want to call a validateFormat() function each time an input of type 'file' changes. Note that a custom directive is used 'file-model'

If I try to add 'ng-change="validateFormat()"' to the input, the console prints the following error: no controller: ngModel.

How can I bind this element to ng-change?

Html

<div ng-controller="MyControllerController">
    <input type="file" file-model="file" />
    <button ng-click="uploadFile()">Upload</button>
    {{error}}
</div>

Angular 1.x:

var module = angular.module("umbraco");

module.controller('OnlineServices.JobCentreUploadController', [
                  '$scope', 'fileUpload', function($scope,         
$scope.uploadFile = function () {
      var file = $scope.file;
      var uploadUrl = "/umbraco/api/jc/Upload";
      fileUpload.uploadFileToUrl(file, uploadUrl, $scope);
    };
}]);

module.directive('fileModel', ['$parse', function ($parse) {
return {
    restrict: 'A',
    link: function (scope, element, attrs) {
        var model = $parse(attrs.fileModel);
        var modelSetter = model.assign;

        element.bind('change', function () {
            scope.$apply(function () {
                modelSetter(scope, element[0].files[0]);
            });
        });
    }
};
}]);

module.service('fileUpload', ['$http', 'notificationsService', function ($http, notificationsService) {
this.uploadFileToUrl = function (file, uploadUrl) {
    var fd = new FormData();
    fd.append('file', file);
    $http.post(uploadUrl, fd, {
        transformRequest: angular.identity,
        headers: { 'Content-Type': undefined }
    })
    .success(function () {
        notificationsService.success("Success", "File uploaded successfully.");
    })
    .error(function () {
        notificationsService.error("Error", "File has not been uploaded.");
    });
}
}]);

Upvotes: 2

Views: 1982

Answers (1)

Gangadhar Jannu
Gangadhar Jannu

Reputation: 4414

ng-change directive needs ng-model Behind the screen ng-change sets a watch for the corresponding ng-model.

Coming to your problem you are trying to call ng-change without specifying ng-model on it that is the reason for error.

In your custom directive you've created an event handler for change event.

So if you want to set up ng-change event for your input element you can do it in your custom directive only no need to go for ng-change directive.

In order to do so you need to pass your validateFormat function as paramter to custom directive and execute the function in change callback like below:

Example code:

element.bind('change', function () {
    scope.$apply(function () {
        modelSetter(scope, element[0].files[0]);
    });
    //Get this function using isolated scope and call it
    validateFormat();
});

Upvotes: 1

Related Questions