如何注入$ http服务到NG-电网CSV导出插件电网、插件、http、NG

2023-09-13 03:39:54 作者:落雨笙璃

我试图解决在NG-电网的 CSV导出插件:

增加一个配置选项,它接受一个URL IE用户,这URL应该接受的有效载荷JSON EN codeD对象的POST请求,并返回一个CSV,这是必要的,因为IE不会让你从数据-URI链接

下载

不过,因为我比较有限AngularJS,NG-电网和天然气网的插件的认识,我与如何访问$ http服务(我需要使用发布的数据)从插件中挣扎。我的认为的我需要注入,但一切到目前为止,我已经尝试已经失败。

我打算像这样重视IE中的CSV导出按钮,把它当作是在其他浏览器:

  //后的数据IEUrl            $ HTTP({                网址:opts.iEUrl,                方法:POST,                数据:csvData,                标题:{内容类型:应用程序/ x-WWW的形式urlen codeD'}            })错误(功能(数据,状态,头,配置){                $ window.alert(状态);            }); 

但即使到目前为止,访问$ HTTP是打败我!

编辑:赢得了战斗,但不是战争(2天后):

所以,原来我是得太多,通过对插件来获得$ HTTP,$窗口等,他们只是需要通过这样注入控制器启动NG-网格,然后通过:

  VAR csvOpts = {columnOverrides:{OBJ:功能(O){    返回o.no +'|' + o.timeOfDay +'|' + o.E +'|' + o.S +'|' + o.I +'|' + o.pH +'|' + o.v;    }},    iEUrl:下载/ download_as_csv};$ scope.gridOptions = {        数据:'experiment.runs',        showGroupPanel:真实,        插件:[新ngGridCsvExportPlugin(csvOpts,$ HTTP,$窗口,$编译,$过滤器) 

然而,这就是当事情变得困难。事实证明,它是不可能导致文件被下载,而不一些额外的弄虚作假反正作为Ajax请求的一个结果 - CSV数据是由请求很好返回,但不触发的下载

所以,有失败,$ HTTP,我想我会做一个表格,把CSV数据到一个textarea,然后发布数据从正常到我的PHP动作:

  VAR FP = $电网root.find(ngFooterPanel)。        如果(isIEAndUrlProvided){            。VAR csvDataLink previous = $电网root.find('ngFooterPanel .csv的数据形式。');            如果(csvDataLink previous!= NULL){csvDataLink previous.remove(); }            fp.append($编译(angular.element('<窗​​体类=CSV数据格式NAME =csvDataForm行动=+ opts.iEUrl +'>'))(范围));            VAR csvDataLinkCurrent = $电网root.find('ngFooterPanel .csv的数据形式。')。            csvDataLinkCurrent.append($编译(angular.element('< textarea的形式=csvDataForm级=CSV数据形式> csvData< / textarea的>'))(范围));            csvDataLinkCurrent.append($编译(angular.element('<输入类=CSV数据形式的TYPE =提交值=CSV导出>'))(范围));        }        其他{            。VAR csvDataLink previous = $电网root.find('ngFooterPanel .csv的数据链路跨度。');            如果(csvDataLink previous!= NULL){csvDataLink previous.remove(); }            VAR csvDataLinkHtml =<跨度类= \\CSV数据链路跨度拉右\\>中;            csvDataLinkHtml + =< BR>< A HREF = \\的数据:文本/ CSV;字符集= UTF-8;            csvDataLinkHtml + = EN codeURIComponent(csvData);            csvDataLinkHtml + =\\下载= \\Export.csv \\级= \\BTN BTN-默认BTN-XS \\角色= \\按钮\\> CSV导出< / A>< / BR>< /跨度>中;            fp.append(csvDataLinkHtml);        } 
如何安装 XCP ng 和 XCP ng Center

这无疑很好地贴到行动,并允许文件下载...但它是空的 - 出于某种原因,我只是不能让被公布的实际数据......所以,我怕我有在CSV导出插件放弃并准备离开它比我更多的人能够

编辑:侧翼然后行动(2天后):

相反,我已经保存它每次在Cookie中发生变化时(的我的应用程序是完全客户端因此这$ p在页面刷新的情况下,$ pvents数据丢失)。所以,当我火了在IE我的csv文件下载请求,我现在在读在PHP中的cookie并用它来创建CSV文件。一种逃避,但我知道我已经在这个运行的时间和它的作品。

FWIW,如下修改插件:

 函数ngGridCsvExportPlugin(选,$ HTTP,$窗口,$编译,$过滤器){VAR自我=这一点;self.grid = NULL;self.scope = NULL;self.init =功能(范围,网格,服务){    self.grid =网格;    self.scope =范围;    //self.$http = services.http;    功能showDs(){        变种键= [];        VAR downloadNotSupportedAndUrlProvided = FALSE;        //测试支持下载属性:http://stackoverflow.com/questions/12112844/how-to-detect-support-for-the-html5-download-attribute        VAR一个=使用document.createElement('A');        如果(选= NULL&放大器;!&安培; opts.iEUrl = NULL&放大器;!&安培; typeof运算a.download ==未定义)downloadNotSupportedAndUrlProvided = TRUE; // DY        为{keys.push(grid.config.columnDefs [F]点域);}(在grid.config.columnDefs变种F)        VAR csvData ='';        功能csvStringify(STR){            如果(STR == NULL){//我们想捕捉到任何空十岁上下,因此只是==不===                返回'';            }            如果(typeof运算(STR)==='号'){                回报''+ STR;            }            如果(typeof运算(STR)==='布尔'){                返回(STR'真':'假');            }            如果(typeof运算(STR)==='串'){                返回str.replace(//克,,);            }            返回JSON.stringify(STR).replace(//克,,);        }        功能swapLastCommaForNewline(STR){            变种中newstr = str.substr(0,str.length  -  1);            返回+中newstr\\ n;        }        为(以VAR键K){            csvData + ='+ csvStringify(键[K])+',';            }        csvData = swapLastCommaForNewline(csvData);        VAR的GridData = grid.data;        为(以VAR的GridData gridRow){            对(在密钥K){                VAR curCellRaw;                如果(选= NULL&放大器;!&安培; opts.columnOverrides = NULL&放大器;!&安培;!opts.columnOverrides [键[K] = NULL){                    curCellRaw = opts.columnOverrides [密钥[K](的GridData [gridRow] [密钥[K]);                }                其他{                    curCellRaw =的GridData [gridRow] [密钥[K]];                }                csvData + ='+ csvStringify(curCellRaw)+',';            }            csvData = swapLastCommaForNewline(csvData);        }        。VAR FP = $电网root.find(ngFooterPanel。);        。VAR csvDataLink previous = $电网root.find('ngFooterPanel .csv的数据链路跨度。');        如果(csvDataLink previous!= NULL){csvDataLink previous.remove(); }        如果(gridData.length大于0){            如果(downloadNotSupportedAndUrlProvided){                fp.append($编译(angular.element('<跨度类= \\CSV数据链路跨度拉右\\>'))(范围));                VAR csvDataSpan = $电网root.find('ngFooterPanel .csv的数据链路跨度。')。                csvDataSpan.append($编译(angular.element('<窗​​体类=CSV数据格式NAME =csvDataForm行动=+ opts.iEUrl +'>'))(范围));                VAR csvDataForm = $电网root.find('ngFooterPanel .csv的数据形式。')。                csvDataForm.append($编译(angular.element('<输入类=BTN-默认BTN-XS类型=提交值=CSV导出>'))(范围));                }            其他{                VAR csvDataLinkHtml =<跨度类= \\CSV数据链路跨度拉右\\>中;                csvDataLinkHtml + =< BR>< A HREF = \\的数据:文本/ CSV;字符集= UTF-8;                csvDataLinkHtml + = EN codeURIComponent(csvData);                csvDataLinkHtml + =\\下载= \\Export.csv \\级= \\BTN BTN-默认BTN-XS \\角色= \\按钮\\> CSV导出< / A>< / BR>< /跨度>中;                fp.append(csvDataLinkHtml);                }            }        }    的setTimeout(showDs,0);    scope.catHashKeys =功能(){        VAR哈希='';        对(在scope.renderedRows VAR IDX){            哈希+ = scope.renderedRows [IDX] $$ hashKey。        }        返回哈希;    };    如果(opts.customDataWatcher){        范围$腕表(opts.customDataWatcher,showDs)。    }其他{        范围$腕表(scope.catHashKeys,showDs)。    }    scope.downloadCsv =功能(){        $ HTTP({            网址:opts.iEUrl,            方法:POST,            数据:$过滤器('JSON')(scope.csvData)            //头:{内容类型:应用程序/ x-WWW的形式urlen codeD'}        })错误(功能(数据,状态,头,配置){            $ window.alert(状态);        });    };}; 

}

解决方案

这是不是真的有必要。修改插件使用FileSaver.js和使用这样的:

\r\r

//现在保存到一个文件!\rVAR getArrayBuffer =功能(){\rVAR数据= csvData,LEN = data.length,\rAB =新ArrayBuffer(LEN),U8 =新Uint8Array(AB);\r而(len--)U8 [长度] = data.char $ C $猫(LEN);\r返回AB;\r};\r\rVAR getBlob =功能(){\r返回新的Blob([getArrayBuffer(){类型:文本/ CSV});\r},\r\r的saveAs(getBlob(),文件名);

\r\r\r

I am trying to tackle a TODO in the ng-grid csv export plugin:

"add a config option for IE users which takes a URL. That URL should accept a POST request with a JSON encoded object in the payload and return a CSV. This is necessary because IE doesn't let you download from a data-uri link"

However, because of my somewhat limited understanding of AngularJS, ng-grid and ng-grid plugins, I am struggling with how to access the $http service (which I need to use to post the data) from within the plugin. I think I need to inject it but everything I've tried so far has failed.

I'm intending to attach something like this to the CSV Export button in IE while leaving it as is in other browsers:

       //post data to IEUrl
            $http({
                url: opts.iEUrl,
                method: "POST",
                data: csvData,
                headers: {'Content-Type': 'application/x-www-form-urlencoded'}
            }).error(function(data, status, headers, config) {
                $window.alert(status);
            });

but so far even accessing $http is defeating me!

EDIT: WON THE BATTLE BUT NOT THE WAR (2 days later):

So, turns out I was overthinking it, to get $http, $window, etc. through to the plugin, they simply needed to be injected into the controller initiating the ng-grid and then passed through thus:

var csvOpts = { columnOverrides: { obj: function (o) {
    return o.no + '|' + o.timeOfDay + '|' + o.E + '|' + o.S+ '|' + o.I+ '|' + o.pH+ '|' + o.v;
    } },
    iEUrl: 'downloads/download_as_csv'
};

$scope.gridOptions = { 
        data: 'experiment.runs',
        showGroupPanel: true,
        plugins: [new ngGridCsvExportPlugin(csvOpts,$http,$window,$compile,$filter)]

However, that's when things got difficult. Turns out that it is not possible to cause a file to be downloaded, without some extra trickery anyway, as a results of an ajax request - the csv data is returned nicely by the request but doesn't trigger the download.

So, having failed with $http, I thought I'd make a form, put the csv data into a textarea and then post the data off as normal to my PHP action:

var fp = grid.$root.find(".ngFooterPanel");
        if(isIEAndUrlProvided){
            var csvDataLinkPrevious = grid.$root.find('.ngFooterPanel .csv-data-form');
            if (csvDataLinkPrevious != null) {csvDataLinkPrevious.remove() ; }
            fp.append($compile(angular.element('<form class="csv-data-form" name="csvDataForm" action="'+opts.iEUrl+'">'))(scope));
            var csvDataLinkCurrent = grid.$root.find('.ngFooterPanel .csv-data-form');
            csvDataLinkCurrent.append($compile(angular.element('<textarea form="csvDataForm" class="csv-data-form">csvData</textarea>'))(scope));
            csvDataLinkCurrent.append($compile(angular.element('<input class="csv-data-form" type="submit" value="CSV Export">'))(scope));
        }
        else {
            var csvDataLinkPrevious = grid.$root.find('.ngFooterPanel .csv-data-link-span');
            if (csvDataLinkPrevious != null) {csvDataLinkPrevious.remove() ; }
            var csvDataLinkHtml = "<span class=\"csv-data-link-span pull-right\">";
            csvDataLinkHtml += "<br><a href=\"data:text/csv;charset=UTF-8,";
            csvDataLinkHtml += encodeURIComponent(csvData);
            csvDataLinkHtml += "\" download=\"Export.csv\" class=\"btn btn-default btn-xs\" role=\"button\">CSV Export</a></br></span>" ;
            fp.append(csvDataLinkHtml);
        }

This certainly posted nicely to the action and allowed the file download...but it was empty - for some reason, I just couldn't get the actual data to be posted...so, I'm afraid I have given up on the csv export plugin and am leaving it for someone more capable than I.

EDIT: A FLANKING MANOEUVRE (2 days later):

Instead, I'm already saving the data which populates the grid every time it changes in a cookie (my app is completely client-side so this prevents data loss in the event of a page refresh). So, when I fire off my csv file download request in IE, I'm now reading the cookie in PHP and using that to create the csv file. A cop-out I know but I've run out of time on this and it works.

FWIW, modified plugin below:

function ngGridCsvExportPlugin (opts, $http,$window,$compile,$filter) {
var self = this;
self.grid = null;
self.scope = null;
self.init = function(scope, grid, services) {
    self.grid = grid;
    self.scope = scope;
    //self.$http = services.http;
    function showDs() {
        var keys = [];
        var downloadNotSupportedAndUrlProvided = false;
        //test for support of download attribute: http://stackoverflow.com/questions/12112844/how-to-detect-support-for-the-html5-download-attribute
        var a = document.createElement('a');
        if(opts != null && opts.iEUrl !=null && typeof a.download == "undefined")downloadNotSupportedAndUrlProvided=true;//DY
        for (var f in grid.config.columnDefs) { keys.push(grid.config.columnDefs[f].field);}
        var csvData = '';
        function csvStringify(str) {
            if (str == null) { // we want to catch anything null-ish, hence just == not ===
                return '';
            }
            if (typeof(str) === 'number') {
                return '' + str;
            }
            if (typeof(str) === 'boolean') {
                return (str ? 'TRUE' : 'FALSE') ;
            }
            if (typeof(str) === 'string') {
                return str.replace(/"/g,'""');
            }

            return JSON.stringify(str).replace(/"/g,'""');
        }
        function swapLastCommaForNewline(str) {
            var newStr = str.substr(0,str.length - 1);
            return newStr + "\n";
        }
        for (var k in keys) {
            csvData += '"' + csvStringify(keys[k]) + '",';
            }
        csvData = swapLastCommaForNewline(csvData);
        var gridData = grid.data;
        for (var gridRow in gridData) {
            for ( k in keys) {
                var curCellRaw;
                if (opts != null && opts.columnOverrides != null && opts.columnOverrides[keys[k]] != null) {
                    curCellRaw = opts.columnOverrides[keys[k]](gridData[gridRow][keys[k]]);
                }
                else {
                    curCellRaw = gridData[gridRow][keys[k]];
                }
                csvData += '"' + csvStringify(curCellRaw) + '",';
            }
            csvData = swapLastCommaForNewline(csvData);
        }
        var fp = grid.$root.find(".ngFooterPanel");
        var csvDataLinkPrevious = grid.$root.find('.ngFooterPanel .csv-data-link-span');
        if (csvDataLinkPrevious != null) {csvDataLinkPrevious.remove() ; }
        if(gridData.length>0){
            if(downloadNotSupportedAndUrlProvided){
                fp.append($compile(angular.element('<span class=\"csv-data-link-span pull-right\">'))(scope));
                var csvDataSpan = grid.$root.find('.ngFooterPanel .csv-data-link-span');
                csvDataSpan.append($compile(angular.element('<form class="csv-data-form" name="csvDataForm" action="'+opts.iEUrl+'">'))(scope));
                var csvDataForm = grid.$root.find('.ngFooterPanel .csv-data-form');
                csvDataForm.append($compile(angular.element('<input class="btn-default btn-xs" type="submit" value="CSV Export">'))(scope));
                }
            else {
                var csvDataLinkHtml = "<span class=\"csv-data-link-span pull-right\">";
                csvDataLinkHtml += "<br><a href=\"data:text/csv;charset=UTF-8,";
                csvDataLinkHtml += encodeURIComponent(csvData);
                csvDataLinkHtml += "\" download=\"Export.csv\" class=\"btn btn-default btn-xs\" role=\"button\">CSV Export</a></br></span>" ;
                fp.append(csvDataLinkHtml);
                }
            }
        }
    setTimeout(showDs, 0);
    scope.catHashKeys = function() {
        var hash = '';
        for (var idx in scope.renderedRows) {
            hash += scope.renderedRows[idx].$$hashKey;
        }
        return hash;
    };
    if (opts.customDataWatcher) {
        scope.$watch(opts.customDataWatcher, showDs);
    } else {
        scope.$watch(scope.catHashKeys, showDs);
    }

    scope.downloadCsv = function(){
        $http({
            url: opts.iEUrl,
            method: 'POST',
            data: $filter('json')(scope.csvData),
            //headers: {'Content-Type': 'application/x-www-form-urlencoded'}
        }).error(function(data, status, headers, config) {
            $window.alert(status);
        });
    };

};

}

解决方案

That isn't really necessary. Modify the plugin to use FileSaver.js and use something like:

 	// now save to a file!
	var getArrayBuffer = function() {
		var data = csvData, len = data.length,
			ab = new ArrayBuffer(len), u8 = new Uint8Array(ab);
		while(len--) u8[len] = data.charCodeAt(len);
		return ab;
	};
		
	var getBlob = function() {
		return new Blob([getArrayBuffer()], { type : "text/csv" });
	},

saveAs(getBlob(), fileName);