我正在尝试遵循此[tutorial]但无法使其正常运行。
我的Angular控制器正在为我的指令中创建的模型记录undefined
。
这是[JSFiddle]的工作,创建了我的教程作者。
问题是视图可以找到$scope.myFile
但控制器没有找到($scope.myFile
是undefined
)。
视图显示{{ myFile.name }}
(仅作为示例my-image.jpg
)。 myFile
变量是包含所选文件数据的JS对象。这很好用。该指令似乎是为模型分配所选文件的值(因此在视图中正确显示它)。
<input file-model="myFile" type="file"/ >
<div class="label label-info">
{{ myFile.name }}
</div>
<button ng-click="uploadDocs()">Click</button>
这是我从[tutorial]获得的指令。
由于输入类型file
无法使用ng-model
,因此该指令将模型设置为与file
输入关联,并在每次文件触发时为其分配{{1事件。
change
在控制器中我只记录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(){
if (element[0].files.length > 1) {
modelSetter(scope, element[0].files);
}
else {
modelSetter(scope, element[0].files[0]);
}
});
});
}
};
}
]).
。这是从上面HTML中的按钮调用的。
理想情况下,我会在这里将文件上传到服务器,但我不能,因为$scope.myFile
未定义。
$scope.myFile
有人可以告诉我为什么视图会收到$scope.uploadDocs = function() {
var file = $scope.myFile;
console.log($scope.myFile);
};
,但控制器会为$scope.myFile
记录undefined
吗?
答案 0 :(得分:5)
我在尝试从控制器访问指令变量时遇到了同样的问题。在我的情况下,我可以让myFile
可用于控制器,但我必须从指令中将其分配给scope.$parent.$parent.myFile
。为了访问变量,我不想在祖先的深度硬编码,所以我最终使用服务在指令和控制器之间共享变量:
.factory('fileService', function() {
var files = [];
return files;
})
我的指令代码更改为使用服务而不是教程中使用的attrs.fileModel
:
.directive('fileModel', ['$parse', 'fileService', function ($parse, fileService) {
return {
restrict: 'A',
link: function(scope, element) {
element.bind('change', function(){
scope.$apply(function(){
if (element[0].files != undefined) {
fileService.push(element[0].files[0]);
console.log('directive applying with file');
}
});
});
}
};
}])
然后,在将fileService注入控制器后,我可以直接从fileService访问该文件:
$scope.uploadDocs = function() {
console.log(fileService);
};
答案 1 :(得分:1)
在几个Angular版本中可以看到此问题,其中file对象无法设置范围变量。作为一个解决方法,将字段传递给控制器,使用此文件对象上传(而不是从范围)
HTML表单
<form>
<div class="form-group">
<label for="myFileField">Select a file: </label>
<input type="file" file-model="myFile" /> <label>File Name:</label>
<input type="text" ng-model="filename"></input>
</div>
<button ng-click="uploadFile(myFile)" class="btn btn-primary">Upload File</button>
</form>
<强>控制器强>
$scope.uploadFile = function (file1) {
var file = $scope.myFile; // this is undefined
console.log("My file =" +file1); // you get this
// Make http call to upload the file or make service call
}
希望这能解决问题
答案 2 :(得分:0)
我已经看过该教程但是选择使用这个库可以使文件无缝上传: ng-file-upload
答案 3 :(得分:0)
尝试以下解决方案: HTML代码:
<div class="btn-header">
<label for="attachment" class="control-label">Attachment</label>
<div class="has-feedback">
<input type="file" id="fileUpload" name="attachment" ng-disabled="BRPTab.BRPTelePhonyandTestScipt.Checked"
class="form-control" data-ak-file-model="BRPTab.tutorial.attachment" />
<span class="form-control-feedback" aria-hidden="true"></span>
<div class="help-block with-errors"></div>
</div>
</div>
服务代码:
AppService.factory("entityService", ["akFileUploaderService", function(akFileUploaderService) {
var saveTutorial = function(tutorial, url) {
return akFileUploaderService.saveModel(tutorial, url);
};
return {
saveTutorial: saveTutorial
};
}]);
(function() {
"use strict"
angular.module("akFileUploader", [])
.factory("akFileUploaderService", ["$q", "$http",
function($q, $http) {
var getModelAsFormData = function(data) {
var dataAsFormData = new FormData();
angular.forEach(data, function(value, key) {
dataAsFormData.append(key, value);
});
return dataAsFormData;
};
var saveModel = function(data, url) {
var deferred = $q.defer();
$http({
url: url,
method: "POST",
//data:
// {
// tutorial: getModelAsFormData(data),
// Object: Obj
// },
//params: Indata,
data: getModelAsFormData(data),
transformRequest: angular.identity,
headers: {
'Content-Type': undefined
}
}).success(function(result) {
deferred.resolve(result);
}).error(function(result, status) {
deferred.reject(status);
});
return deferred.promise;
};
return {
saveModel: saveModel
}
}
])
.directive("akFileModel", ["$parse",
function($parse) {
return {
restrict: "A",
link: function(scope, element, attrs) {
var model = $parse(attrs.akFileModel);
var modelSetter = model.assign;
element.bind("change", function() {
scope.$apply(function() {
modelSetter(scope, element[0].files[0]);
});
});
}
};
}
]);
})(window, document);
如果你们有任何问题,请告诉我。
答案 4 :(得分:0)
试试这段代码
<html>
<head>
<script src = "https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
</head>
<body ng-app = "myApp">
<div ng-controller = "myCtrl">
<input type = "file" file-model = "myFile"/>
<button ng-click = "uploadFile()">upload me</button>
</div>
<script>
var myApp = angular.module('myApp', []);
myApp.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]);
});
});
}
};
}]);
myApp.service('fileUpload', ['$http', function ($http) {
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(){
})
.error(function(){
});
}
}]);
myApp.controller('myCtrl', ['$scope', 'fileUpload', function($scope, fileUpload){
$scope.uploadFile = function(){
var file = $scope.myFile;
console.log('file is ' );
console.dir(file);
var uploadUrl = "/fileUpload";
fileUpload.uploadFileToUrl(file, uploadUrl);
};
}]);
</script>
</body>
</html>