【问题标题】:Dropdown closed in ng-repeat when data is refreshed刷新数据时,下拉菜单在 ng-repeat 中关闭
【发布时间】:2015-02-03 08:54:40
【问题描述】:

我使用 $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 指令显示在表格中,我显示了一个引导下拉菜单:

<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 的数据,如果它们相同,则不更新 $scope。但是,即使 $http.get 被触发,下拉菜单也会关闭即使我没有更新范围变量

我希望能够在不关闭的情况下轮询和显示下拉菜单。但是,如果在数据真正更改但不是在每次民意调查时关闭下拉菜单,这将是合理的。

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

【问题讨论】:

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


    【解决方案1】:

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

    (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,但涉及更多工作,我必须尝试一下。感谢您的回答。
    • 是的。它要复杂得多,但这意味着除非删除显示下拉列表的项目,否则下拉列表不会关闭。我的代码中有一个错误,项目不会被删除。我现在已经解决了。这是正在删除的项目的demo
    【解决方案2】:

    您可以使用angular.equals检查对象是否等价

    if(!angular.equals($scope.cities, data.list)) {
                $scope.cities = data.list;
    }
    

    Plunkr demo

    【讨论】:

    • 如果项目被修改或添加新项目,这仍然会导致同样的问题。
    • 这是对的,但只有在添加新项目时才可以(根据问题要求)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-28
    • 2014-06-13
    • 2017-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多