刷新数据时,下拉菜单以ng-repeat关闭

时间:2015-02-03 08:54:40

标签: javascript angularjs twitter-bootstrap drop-down-menu angularjs-ng-repeat

我使用$ 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指令显示在表格中,我显示了一个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,即使我不更新范围变量,下拉也会关闭

我希望能够在不关闭的情况下轮询并显示下拉菜单。如果在数据真正改变时关闭下拉但在每次轮询时没有关闭,那将是合理的。

这是一个显示效果的plunker:http://plnkr.co/edit/yqYsQ32XaAhZEsD2XWMu?p=preview

2 个答案:

答案 0 :(得分:2)

您应该只更新现有对象,或者如果有任何新项目,则将其添加到数组中,而不是不断更新数组并添加对象。当您尝试这样做时,您不断更改数组值而不是仅更改对象。

(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);
    });
})();

Plunkr

答案 1 :(得分:1)

您可以使用angular.equals

检查对象是否相同
if(!angular.equals($scope.cities, data.list)) {
            $scope.cities = data.list;
}

Plunkr demo