AngularJS:如何在控制器中使用过滤后数组的长度值
The issue you're facing is because the test variable you're assigning in the ng-repeat lives in the child scope created by ng-repeat, not your main controller's scope. That's why you can see it in the template but can't access it in the controller. Here are two straightforward fixes:
Option 1: Move Filter Logic to the Controller (Recommended)
This is the cleanest approach because it keeps your business logic in the controller where it belongs, making it easier to test and maintain.
Step 1: Update Your Controller
Add code to handle the filtering and store the result in a controller-scoped variable. You'll need to inject the $filter service:
app.controller('YourController', function($scope, $filter) { // Initialize the filtered array with the full tree $scope.filteredNodes = angular.copy($scope.product.versions.tree); // Watch for changes in the search query to update the filtered array $scope.$watch('search.query', function(newQuery) { if (newQuery) { $scope.filteredNodes = $filter('filter')($scope.product.versions.tree, newQuery); } else { // Reset to full tree when query is empty $scope.filteredNodes = angular.copy($scope.product.versions.tree); } }); // Now you can access the length anywhere in the controller! // Example: $scope.doSomethingWithLength = function() { console.log('Filtered length:', $scope.filteredNodes.length); }; });
Step 2: Update Your Template
Replace the inline filter with the controller-managed filteredNodes variable:
<div ui-tree id="tree-root"> <ol ui-tree-nodes ng-model="product.versions.tree"> <li ng-repeat="node in filteredNodes" ui-tree-node collapsed='collpsed' ng-include="'nodes_renderer.html'"></li> <p>{{filteredNodes.length}}</p> </ol> </div>
Option 2: Assign to a Parent Scope Object (If You Want to Keep Filter in Template)
If you prefer to keep the filter in the template, you can work around the scope issue by assigning the filtered result to a property of an object that exists in your controller's scope (since child scopes inherit object references, not primitive values).
Step 1: Add an Object to Your Controller
Create an empty object in your controller to hold the filtered result:
app.controller('YourController', function($scope) { $scope.filteredData = {}; // Now you can access the length via: // $scope.filteredData.test.length });
Step 2: Update Your Template
Modify the ng-repeat to assign to the object property instead of a primitive variable:
<div ui-tree id="tree-root"> <ol ui-tree-nodes ng-model="product.versions.tree"> <li ng-repeat="node in (filteredData.test=(product.versions.tree | filter:search.query))" ui-tree-node collapsed='collpsed' ng-include="'nodes_renderer.html'"></li> <p>{{filteredData.test.length}}</p> </ol> </div>
Now your controller can access $scope.filteredData.test.length whenever you need it.
Bonus Tip: Use ControllerAs Syntax (Avoid Scope Conflicts Altogether)
If you're using controllerAs syntax (e.g., ng-controller="YourController as vm"), you can directly assign the filtered result to the controller instance, which avoids scope inheritance issues entirely:
Template:
<li ng-repeat="node in (vm.filteredNodes=(product.versions.tree | filter:search.query))" ...></li>
Controller:
app.controller('YourController', function() { var vm = this; // Access via vm.filteredNodes.length });
内容的提问来源于stack exchange,提问作者midoxNava

