如何将AngularJS视图中过滤后的值传递至控制器?
解决方案:将过滤器计算结果传递到AngularJS控制器
这问题我之前做项目时也碰到过,给你分享几个实用的方案,按推荐程度排序:
1. 控制器直接调用过滤器服务(最推荐)
AngularJS的过滤器本质上是可以注入到控制器的服务,直接在控制器里调用它计算总和,既能让控制器拿到值,还能避免视图和控制器重复计算,逻辑也更可控。
步骤:
- 在控制器中注入
sumProductFilter(过滤器名+Filter后缀) - 调用过滤器计算总时长,绑定到$scope变量
- 如果数据是异步加载的,用
$watch监听数组变化,实时更新总和
app.controller('VideoListController', ['$scope', 'sumProductFilter', function($scope, sumProductFilter) { // 假设你的视频数组初始数据(如果是异步的,后续从接口获取后赋值即可) $scope.videoList = [ {meta_duration: 120}, {meta_duration: 180}, {meta_duration: 240} ]; // 初始化计算总时长 $scope.totalDuration = sumProductFilter($scope.videoList, 'meta_duration'); // 监听视频数组的变化(新增/删除/修改时自动更新总和) $scope.$watch('videoList', function(newVideos) { if (newVideos && newVideos.length > 0) { $scope.totalDuration = sumProductFilter(newVideos, 'meta_duration'); } else { $scope.totalDuration = 0; } }, true); // 第三个参数true表示深度监听数组内元素的变化 }]);
视图里直接使用{{totalDuration}}即可,同时ng-repeat正常展示视频:
<div ng-repeat="video in videoList"> 时长:{{video.meta_duration}}秒 </div> <p>总时长:{{totalDuration}}秒</p>
2. 用ng-init绑定结果到控制器变量(简单场景适用)
如果你的视频数据是静态或者加载完成后不会变化,用ng-init直接把过滤器的计算结果赋值给$scope变量是最快的方式。
视图代码:
<div ng-init="totalDuration = videoList | sumProduct:'meta_duration'"> <div ng-repeat="video in videoList"> 时长:{{video.meta_duration}}秒 </div> <p>总时长:{{totalDuration}}秒</p> </div>
控制器里不需要额外代码,直接通过$scope.totalDuration就能访问这个值。注意:如果视频数组是异步加载的,要确保ng-init在数据加载完成后执行,否则会计算出0。
3. 过滤器内广播结果(不推荐,仅特殊场景用)
过滤器的设计初衷是纯函数(输入相同则输出相同,无副作用),所以尽量不要在过滤器里做事件广播这类操作,但如果有特殊需求,可以通过$rootScope把计算结果广播给控制器。
修改后的过滤器代码:
app.filter('sumProduct', ['$rootScope', function($rootScope) { // 辅助函数:获取嵌套属性值 function getNestedPropertyByKey(obj, keyArray) { let result = obj; for (const key of keyArray) { if (!result || typeof result !== 'object') return null; result = result[key]; } return result; } return function(input) { const isArray = input instanceof Array; if (!isArray || input.length === 0) { $rootScope.$broadcast('sumProductCalculated', 0); return 0; } let total = 0; // 遍历传入的属性参数(除了第一个input参数) for (let i = 1; i < arguments.length; i++) { const keyPath = arguments[i].split('.'); input.forEach(item => { const value = getNestedPropertyByKey(item, keyPath); if (!isNaN(value)) { total += parseFloat(value); } }); } // 广播计算结果 $rootScope.$broadcast('sumProductCalculated', total); return total; }; }]);
控制器监听广播:
app.controller('VideoListController', ['$scope', function($scope) { $scope.totalDuration = 0; // 监听过滤器广播的结果 $scope.$on('sumProductCalculated', function(event, result) { $scope.totalDuration = result; }); }]);
补充:完善你的sumProduct过滤器
你提供的过滤器代码片段有未完成的部分(比如getNestedPropertyByKey函数、总和计算逻辑),上面的示例已经补全了这部分,确保它能正确计算嵌套属性的总和。
内容的提问来源于stack exchange,提问作者Arter
相关产品推荐
相关产品推荐

