刷新数据时在 ng-repeat 中关闭下拉菜单
Dropdown closed in ng-repeat when data is refreshed
我使用 $http 获取数据并每 1 秒刷新一次(服务器轮询):
(function tick(){
$http.get('http://api.openweathermap.org/data/2.5/group?id=524901,703448,2643743&units=metric')
.success(function (data) {
console.log('tick');
$scope.cities = data.list;
$timeout(tick, 1000);
});
})();
此数据使用 ng-repeat 指令显示在 table 中,我显示 bootstrap 下拉菜单:
<tr ng-repeat="city in cities">
<td>{{city.name}}</td>
<td>
<div class="dropdown">
<button type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Dropdown
</button>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<li><button>Buttons</button></li>
<li><button>Are closed</button></li>
<li><button>When $scope variable</button></li>
<li><button>is refreshed</button></li>
</ul>
</div>
</td>
</tr>
问题是当我打开下拉菜单时,它会在函数 tick() 运行 后立即关闭。
我已经尝试比较来自 $http.get 和范围的数据,并且不更新 $scope 以防它们相同。但是,即使 $http.get 被触发,下拉菜单也会关闭 ,即使我不更新范围变量 。
我希望能够在不关闭的情况下轮询和显示下拉菜单。如果下拉列表在数据真正更改时关闭而不是在每次轮询时关闭,那将是合理的。
这是一个展示效果的插件:http://plnkr.co/edit/yqYsQ32XaAhZEsD2XWMu?p=preview
您可以使用 angular.equals
检查对象是否等价
if(!angular.equals($scope.cities, data.list)) {
$scope.cities = data.list;
}
与其不断更新数组和添加对象,不如只更新现有对象,或者如果有任何新项目,则将它们添加到数组中。当您尝试这样做时,您一直在更改数组值,而不仅仅是更改对象。
(function tick(){
$http.get('http://api.openweathermap.org/data/2.5/group?id=524901,703448,2643743&units=metric')
.success(function (data) {
if ($scope.cities.length === 0) {
$scope.cities = data.list;
}
else{
for (var i = 0; i < data.list.length; i++) {
var dataCity = data.list[i];
var found = false;
for (var j = 0; j < $scope.cities.length; j++) {
var city = $scope.cities[j];
if (dataCity.id === city.id) {
found = true;
if (!angular.equals(city, dataCity)) {
angular.copy(dataCity, city);
}
break;
}
}
if (!found) {
$scope.cities.push(dataCity);
}
}
for (var k = 0; k < $scope.cities.length; k++) {
var cityToCheck = $scope.cities[k];
var cityFound = false;
for (var l = 0; l < data.list.length; l++) {
var dataToCheck = data.list[l];
if (dataToCheck.id === cityToCheck.id) {
cityFound = true;
break;
}
}
if (!cityFound) {
$scope.cities.splice(k, 1);
k--;
}
}
}
$timeout(tick, 1000);
});
})();
我使用 $http 获取数据并每 1 秒刷新一次(服务器轮询):
(function tick(){
$http.get('http://api.openweathermap.org/data/2.5/group?id=524901,703448,2643743&units=metric')
.success(function (data) {
console.log('tick');
$scope.cities = data.list;
$timeout(tick, 1000);
});
})();
此数据使用 ng-repeat 指令显示在 table 中,我显示 bootstrap 下拉菜单:
<tr ng-repeat="city in cities">
<td>{{city.name}}</td>
<td>
<div class="dropdown">
<button type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Dropdown
</button>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<li><button>Buttons</button></li>
<li><button>Are closed</button></li>
<li><button>When $scope variable</button></li>
<li><button>is refreshed</button></li>
</ul>
</div>
</td>
</tr>
问题是当我打开下拉菜单时,它会在函数 tick() 运行 后立即关闭。
我已经尝试比较来自 $http.get 和范围的数据,并且不更新 $scope 以防它们相同。但是,即使 $http.get 被触发,下拉菜单也会关闭 ,即使我不更新范围变量 。
我希望能够在不关闭的情况下轮询和显示下拉菜单。如果下拉列表在数据真正更改时关闭而不是在每次轮询时关闭,那将是合理的。
这是一个展示效果的插件:http://plnkr.co/edit/yqYsQ32XaAhZEsD2XWMu?p=preview
您可以使用 angular.equals
检查对象是否等价if(!angular.equals($scope.cities, data.list)) {
$scope.cities = data.list;
}
与其不断更新数组和添加对象,不如只更新现有对象,或者如果有任何新项目,则将它们添加到数组中。当您尝试这样做时,您一直在更改数组值,而不仅仅是更改对象。
(function tick(){
$http.get('http://api.openweathermap.org/data/2.5/group?id=524901,703448,2643743&units=metric')
.success(function (data) {
if ($scope.cities.length === 0) {
$scope.cities = data.list;
}
else{
for (var i = 0; i < data.list.length; i++) {
var dataCity = data.list[i];
var found = false;
for (var j = 0; j < $scope.cities.length; j++) {
var city = $scope.cities[j];
if (dataCity.id === city.id) {
found = true;
if (!angular.equals(city, dataCity)) {
angular.copy(dataCity, city);
}
break;
}
}
if (!found) {
$scope.cities.push(dataCity);
}
}
for (var k = 0; k < $scope.cities.length; k++) {
var cityToCheck = $scope.cities[k];
var cityFound = false;
for (var l = 0; l < data.list.length; l++) {
var dataToCheck = data.list[l];
if (dataToCheck.id === cityToCheck.id) {
cityFound = true;
break;
}
}
if (!cityFound) {
$scope.cities.splice(k, 1);
k--;
}
}
}
$timeout(tick, 1000);
});
})();