我有这个html
<input type="file" file-input="files" multiple />
<button ng-click="upload()" type="button">Upload</button>
<li ng-repeat="file in files">{{file.name}}</li>
该指令:
.directive('fileInput', ['$parse', function($parse){
return {
restrict: 'A',
link: function(scope, elm, attrs){
//console.log("directives scope: ")
elm.bind('change', function(){
$parse(attrs.fileInput)
.assign(scope,elm[0].files)
scope.$apply()
//console.log(scope);
})
}
}
}]);
在我的控制器中,我有这个功能:
$scope.upload=function(){
console.log($scope.files)
var fd = new FormData() // put these 3 lines in a service
angular.forEach($scope.files, function(file){
fd.append('file', file)
})
$http.post('/api/directory/upload-file-test', fd,
{
transformRequest: angular.identity, // returns first argument it is passed
headers:{'Content-Type': undefined} //multipart/form-data
})
.success(function(d){
console.log(d)
console.log("works?")
})
}
如果我像往常一样将 HTML 直接放在 html 文件中,它就可以正常工作,但是......
我需要注入它,当我这样做时,指令范围和控制器范围是不一样的......所以我添加到指令中的 scope.files 的文件只是控制器函数中的"未定义",所以我的文件上传中断了......
更确切地说...
如果我这样做:
<tr ng-repeat="prop in tab.properties">
<td>{{prop.name}}</td>
<td compile ng-bind-html="prop.data_type.html | unsafe"></td>
<td>{{prop.description}}</td>
</tr>
ng-bind-html引号(prop.data_type.html(中的内容刚好等于这个:
<input type="file" file-input="files" multiple />
<button ng-click="upload()" type="button">Upload</button>
<li ng-repeat="file in files">{{file.name}}</li>
它不起作用。范围不同。
我的编译指令如下所示:
.directive('compile',function($compile, $timeout){
return{
restrict:'A',
link: function(scope,elem,attrs){
$timeout(function(){
$compile(elem.contents())(scope);
});
}
};
})
最后一段相关的代码是不安全过滤器,它是这样的:
.filter('unsafe', function($sce) {
return function(val) {
return $sce.trustAsHtml(val);
};
})
有没有人知道为什么我的控制器和指令范围内的"上传"函数不能保持同步并引用相同的范围,并且只有当我通过 ng-bind-html 将我的 html 与我的编译指令和不安全过滤器一起注入时?这有什么问题吗,或者我必须避免使用指令来使其工作?
我首先尝试了 Angular 1.3.0 rc4,现在在我升级到最新版本 v. 1.3.5 后,它仍然是一样的。
我能够解决这个问题,这是简单的解决方案:
(旧代码(:
<input type="file" file-input="files" multiple />
<button ng-click="upload()" type="button">Upload</button>
<li ng-repeat="file in files">{{file.name}}</li>
替换为:
<input type="file" file-input="test.files" multiple />
<button ng-click="upload()" type="button">Upload</button>
<li ng-repeat="file in test.files">{{file.name}}</li>
而这个旧代码:
.directive('fileInput', ['$parse', function($parse){
return {
restrict: 'A',
link: function(scope, elm, attrs){
//console.log("directives scope: ")
elm.bind('change', function(){
$parse(attrs.fileInput)
.assign(scope,elm[0].files)
scope.$apply()
//console.log(scope);
})
}
}
}]);
应该替换为:
.directive('fileInput', ['$parse', function($parse){
return {
restrict: 'A',
link: function(scope, elm, attrs){
if(typeof(scope.test) == undefined){
scope.test = { "files": []}
}
if(typeof(scope.test.files) !== undefined){
scope.test["files"] =[]
}
elm.bind('change', function(){
$parse(attrs.fileInput)
.assign(scope,elm[0].files)
scope.$apply()
})
}
}
}]);
控制器功能也是如此(旧代码优先(:
$scope.upload=function(){
console.log($scope.files)
var fd = new FormData() // put these 3 lines in a service
angular.forEach($scope.files, function(file){
fd.append('file', file)
})
$http.post('/api/directory/upload-file-test', fd,
{
transformRequest: angular.identity, // returns first argument it is passed
headers:{'Content-Type': undefined} //multipart/form-data
})
.success(function(d){
console.log(d)
console.log("works?")
})
}
溶液:
$scope.test = {files:undefined}
$scope.upload=function(){
console.log($scope.test.files)
var fd = new FormData() // put these 3 lines in a service
angular.forEach($scope.test.files, function(file){
fd.append('file', file)
})
$http.post('/api/directory/upload-file-test', fd,
{
transformRequest: angular.identity, // returns first argument it is passed
headers:{'Content-Type': undefined} //multipart/form-data
})
.success(function(d){
console.log(d)
console.log("works?")
})
}
如果你需要更多的解释,智者乔希·大卫·米勒(Josh David Miller(在这里。这是我意识到如何解决这个问题的评论:https://stackoverflow.com/a/15645354/3973406
基本上它与隔离范围无关,但因为我们违反了规则,而 Angular 对此很婊子!