【问题标题】:Angular Directive scope undefined角度指令范围未定义
【发布时间】:2015-08-20 21:50:03
【问题描述】:

我正在使用指令来解析 xls 文件并通过范围将数据传递给按钮。问题是在链接函数中,我绑定到元素更改事件并调用解析 xls 文件的函数,但在 handleFile 函数中未定义范围,因此我无法将数据传递给按钮。将数据获取到按钮的正确方法是什么?

angular.module('fileReaderModule')
.directive('xlsReader', function(){

return {
    scope: {
        search: "&"
    },
    link: function(scope, e, attr) {
        e.bind('change', handleFile);
    },
    template: '<input type="file" ng-model="xlsFile"><button ng-click="search({stuff: scope.stuff})">Search</button>'
}

function handleFile(scope, e) {
    var files = e.target.files;
    var i,f;
    for (i = 0, f = files[i]; i != files.length; ++i) {
        var reader = new FileReader();
        var name = f.name;
        reader.onload = function(e) {
            var data = e.target.result;

            var workbook = XLSX.read(data, {type: 'binary'});
            scope.stuff = workbook.Strings; // scope not available here
            /* DO SOMETHING WITH workbook HERE */
            var result = {};
            workbook.SheetNames.forEach(function(sheetName) {
                var roa = XLSX.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]);
                if(roa.length > 0){
                    result[sheetName] = roa;
                }
            });
        };
        reader.readAsBinaryString(f);
    } 
}
})

【问题讨论】:

    标签: angularjs angularjs-directive angularjs-scope


    【解决方案1】:

    在模板内你不需要使用scope

    替换这个:

    template: '<input type="file" ng-model="xlsFile"><button ng-click="search({stuff: scope.stuff})">Search</button>'
    

    用这个:

    template: '<input type="file" ng-model="xlsFile"><button ng-click="search({stuff: stuff})">Search</button>'
    

    你还应该像这样声明你的函数:

    angular.module('fileReaderModule')
    .directive('xlsReader', function($timeout){
    
        return {
            scope: {
                search: "&"
            },
            link: function(scope, e, attr) {
                e.bind('change', scope.handleFile);
    
                scope.handleFile(e) {
                  var files = e.target.files;
                  var i,f;
                  for (i = 0, f = files[i]; i != files.length; ++i) {
                    var reader = new FileReader();
                    var name = f.name;
                    reader.onload = function(e) {
                        //Async code, need $timeout call so angular runs a digest cycle and updates the bindings
                        $timeout(function(){
                            var data = e.target.result;
    
                            var workbook = XLSX.read(data, {type: 'binary'});
                            scope.stuff = workbook.Strings;
                            var result = {};
                            workbook.SheetNames.forEach(function(sheetName) {
                                var roa = XLSX.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]);
                                if(roa.length > 0){
                                    result[sheetName] = roa;
                                }
                            });
                        });
                    };
                    reader.readAsBinaryString(f);
                }
            }
        },
        template: '<input type="file" ng-model="xlsFile"><button ng-click="search({stuff: stuff})">Search</button>'
    });
    

    【讨论】:

    • 谢谢!不过,关于何时使用 $timeout 并不是很清楚。
    • $timeout 应该用于包装异步代码,以便 Angular 在触发 reader.onload 事件时运行摘要......这会强制 Angular 更新它的所有绑定。我的最后一次编辑显示了它是如何完成的。
    • $scope.$apply() 也是一种替代方法...您可以将其作为 reader.onload 函数中的最后一行运行,但如果角度摘要已在运行,则可能会触发错误.. $timeout 在运行另一个之前等待可能的角度摘要运行,因此可以防止任何错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-20
    • 2016-07-20
    • 1970-01-01
    • 2013-10-04
    • 1970-01-01
    相关资源
    最近更新 更多