AngularJS控制器方法参数无法获取数据修改值的问题求助
兄弟,我仔细看了你的问题,核心问题有两个:一是编辑后的DOM内容没有同步回AngularJS的$scope变量,导致save和export拿到的都是原始数据;二是Cordova Android环境下不能用浏览器的a标签下载逻辑来保存文件。咱们一步步来解决:
一、解决数据同步的核心问题
你现在用{{line}}把oPada.lyrics里的内容渲染到表格,但contenteditable编辑的是DOM节点的内容,AngularJS默认不会把DOM的修改反向同步回$scope(因为{{}}是单向绑定)。所以咱们需要给contenteditable实现双向绑定,写一个自定义指令就能搞定:
1. 添加自定义指令
在你的控制器代码上方加上这个指令:
angular.module('mainApp') .directive('contenteditable', function() { return { require: 'ngModel', link: function(scope, elm, attrs, ctrl) { // 把model的值渲染到view ctrl.$render = function() { elm.html(ctrl.$viewValue || ''); }; // 监听view的修改,同步回model elm.on('blur keyup change', function() { scope.$apply(function() { ctrl.$setViewValue(elm.html()); }); }); } }; });
2. 修改HTML模板
把原来的表格行改成用ng-model绑定,同时把外层的全局contenteditable去掉,换成在每个单元格上控制可编辑状态:
<div class="padaBody"> <table class="padaLyrics"> <tr ng-repeat="line in oPada.lyrics track by $index"> <td contenteditable="{{editMode}}" ng-model="line"></td> </tr> </table> </div>
这样一来,你在编辑表格内容时,修改会自动同步到$scope.oPada.lyrics里,控制器就能拿到最新的修改后数据了。
二、修正控制器的save和export方法
现在数据已经同步到$scope.oPada了,不需要再传参数(之前传oPada可能拿到的是绑定前的旧引用),直接用$scope.oPada即可:
1. 修正save方法
$scope.save = function() { const objectToSave = $scope.oPada; if (!objectToSave) { return; } $http.put('data/pada.json', objectToSave).then( function(response) { $scope.editMode = false; // 找到数组中对应的对象,替换成修改后的版本 const idx = $scope.padas.findIndex(o => o.padaID === response.data.padaID); if (idx !== -1) { $scope.padas.splice(idx, 1, response.data); } }, function(response) { console.error('保存失败:', response); } ); };
2. 修正export方法(适配Cordova Android)
浏览器的a标签下载逻辑在Cordova里不生效,需要用Cordova的cordova-plugin-file插件来实现文件保存:
首先,先安装插件:
cordova plugin add cordova-plugin-file
然后修改export方法:
$scope.export = function() { const objectToExport = $scope.oPada || { string: "empty", number: 2 }; // 生成文件名 const pada = objectToExport.title ? objectToExport.title.replace(/ /g, '_') : objectToExport.padaID ? 'PadaID_' + objectToExport.padaID.toString().padStart(3, '0') : 'PadaID_000'; const filename = pada + '.json'; const blob = new Blob([angular.toJson(objectToExport, true)], { type: 'application/json' }); // 区分Cordova和普通浏览器环境 if (window.cordova) { // Cordova环境:用File API保存到外部存储 window.resolveLocalFileSystemURL(cordova.file.externalDataDirectory, function(dir) { dir.getFile(filename, { create: true }, function(file) { file.createWriter(function(writer) { writer.onwriteend = function() { alert(`文件已保存:${cordova.file.externalDataDirectory}${filename}`); }; writer.onerror = function(err) { console.error('写入文件失败:', err); alert('保存失败,请检查权限'); }; writer.write(blob); }, function(err) { console.error('创建写入器失败:', err); }); }, function(err) { console.error('获取文件对象失败:', err); }); }, function(err) { console.error('获取目录失败:', err); }); } else if (window.navigator && window.navigator.msSaveOrOpenBlob) { // IE浏览器兼容 window.navigator.msSaveOrOpenBlob(blob, filename); } else { // 普通浏览器下载 const a = document.createElement('a'); a.download = filename; a.href = window.URL.createObjectURL(blob); a.dataset.downloadurl = ['application/json', a.download, a.href].join(':'); const e = document.createEvent('MouseEvents'); e.initEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); a.dispatchEvent(e); } };
三、最后调整按钮的点击事件
把原来的ng-click="save(oPada)"和ng-click="export(oPada)"改成不带参数的:
<md-icon class="material-icons" ng-click="save()">save</md-icon> <md-icon class="material-icons" ng-click="export()">download</md-icon>
这样修改后,你点击save时,就能把修改后的oPada数据提交到后端,同时更新$scope.padas数组;点击export时,在浏览器和Cordova Android上都能正确保存修改后的JSON数据了。
备注:内容来源于stack exchange,提问作者DasaAnudas

