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

时间:2014-12-05 22:26:03

标签: angularjs controller scope directive inject

我有这个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);
    };
})

有没有人知道为什么我的“上传”功能在我的控制器和我的指令范围内不能保持同步并且引用相同的范围 IF并且只有在我使用我的编译指令和不安全过滤器注入我的html时NG-绑定-HTML ?反正有这个或者我必须避免使用指令来使这个工作吗?

我首先尝试过Angular 1.3.0 rc4,现在我升级到最新版本v.3.3.5之后仍然是这样。

1 个答案:

答案 0 :(得分:0)

我能够解决这个问题,这是一个简单的解决方案:

(旧代码):

<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是一个关于它的婊子!