在控制器中注入指令时未定义指令/控制器范围



我有这个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 对此很婊子!

最新更新