AngularJS:从下拉列表中选择任何选项时,函数在 ng-change 上触发两次

Posted

技术标签:

【中文标题】AngularJS:从下拉列表中选择任何选项时,函数在 ng-change 上触发两次【英文标题】:AngularJS : function triggers twice on ng-change while selecting any option from dropdown 【发布时间】:2016-04-29 15:05:39 【问题描述】:

实际上我是 angularjs 的新手,我面临的问题让我很困惑。 我已经编写了 angularjs 控制器,它在下拉菜单中填充数据并选择它应该在地图上显示特定位置的每个选项。为了触发事件,我使用了 ng-change。

我的 html 视图看起来像,

<select name="DeviceList" ng-model="deviceList" ng-change="filterMarkers()">
                                        <option value="0" selected="selected">All</option>
                                        <option ng-repeat="device in data" value="device.id">device.name</option>
                                </select>

JSON 对象的样子,

[
"id": 1,
"name": "MacVend1001",
"latitude": "12.9383145",
"longitude": "77.57274628",
"status": "ON",
"failureMessage": null,
"healthIndex": [
    "Parameter": "Voltage",
    "value": "29",
    "y-axis": [244, 124, 226, 372, 180, 290, 135, 350, 175, 145],
    "x-axis": ["2016-01-01 13:49:32", "2016-01-02 13:48:43", "2016-01-03 13:48:43", "2016-01-04 13:48:43", "2016-01-05 13:49:32", "2016-01-06 13:48:43", "2016-01-07 13:48:43", "2016-01-08 13:48:43", "2016-01-09 13:48:43", "2016-01-10 13:48:43"],
    "chart-type": "Trend"
, 
    "Parameter": "Internal Temprature",
    "value": "30",
    "y-axis": [44, 24, 26, 72, 80, 90, 35, 50, 75, 45],
    "x-axis": ["2016-01-01 13:49:32", "2016-01-02 13:48:43", "2016-01-03 13:48:43", "2016-01-04 13:48:43", "2016-01-05 13:49:32", "2016-01-06 13:48:43", "2016-01-07 13:48:43", "2016-01-08 13:48:43", "2016-01-09 13:48:43", "2016-01-10 13:48:43"],
    "chart-type": "Trend"
, 
    "Parameter": "External Temprature",
    "value": "45",
    "y-axis": [144, 224, 126, 372, 180, 2940, 1355, 250, 175, 345],
    "x-axis": ["2016-01-01 13:49:32", "2016-01-02 13:48:43", "2016-01-03 13:48:43", "2016-01-04 13:48:43", "2016-01-05 13:49:32", "2016-01-06 13:48:43", "2016-01-07 13:48:43", "2016-01-08 13:48:43", "2016-01-09 13:48:43", "2016-01-10 13:48:43"],
    "chart-type": "Trend"
]

]

控制器终于来了,

angular.module('mapsApp', [])
.controller('NewMapCtrl', function ($scope,$http) 
    $scope.data=[];
    $http(method:'GET',url: 'https://korbsbvm130.apac.bosch.com:8244/intelrfc/1.0/devicelist').success(function(API_RESPONSE)
        $scope.data=API_RESPONSE;
        $scope.devicelist=0;
    );

    var mapOptions = 
        zoom: 4,
        center: new google.maps.LatLng(40.0000, -98.0000),
        mapTypeId: google.maps.MapTypeId.TERRAIN
    

    $scope.map = new google.maps.Map(document.getElementById('map'), mapOptions);

    $scope.markers = [];

    var infoWindow = new google.maps.InfoWindow();

    var createMarker = function (info) 
        var marker = new google.maps.Marker(
            map: $scope.map,
            position: new google.maps.LatLng(info.lat, info.long),
            title: info.city,
            Name:info.name
        );
        marker.content = '<div class="infoWindowContent">' + info.desc + '</div><div class="infoWindowContent">' + info.city + '</div><div class="infoWindowContent">' + info.name + '</div>';

        google.maps.event.addListener(marker, 'click', function () 
            infoWindow.setContent('<h2>' + marker.Name +'<h2>' + marker.title + '</h2>' + marker.content);
            infoWindow.open($scope.map, marker);
        );
        $scope.markers.push(marker);
    

  for (i = 0; i < $scope.data.length; i++) 
        createMarker($scope.data[i]);
    

    $scope.openInfoWindow = function (e, selectedMarker) 
        e.preventDefault();
        google.maps.event.trigger(selectedMarker, 'click');
    

    $scope.clearMarkers = function() 
      for (var i = 0; i < $scope.markers.length; i++) 
        $scope.markers[i].setMap(null);
      
      $scope.markers.length = 0;
    



    $scope.filterMarkers = function() 
       //1.select filtered cities
       var devicesData;
       var deviceName = $scope.deviceList;
       if(deviceName == '0') 
          devicesData = $scope.data;
       
       else 
          devicesData = $scope.data.filter(function(c)
              alert("C.id="+c.id)
            if(c.id == deviceName)
               return c; 
          );
         
       //2.update markers on map
       $scope.clearMarkers();
       for (i = 0; i < devicesData.length; i++) 
        createMarker(devicesData[i]);
       
    

);

现在的问题是,每当我从填充的下拉列表中单击任何选项时,它都会调用 filtermarkers() 函数两次,但通常它不应该。请分享您的想法如何摆脱它。

它还在填充的下拉列表中显示了两个空选项。

【问题讨论】:

【参考方案1】:

你可能只是没有正确配置 select 指令。我不记得在 select 指令中看到 value 属性。这是一个显示简单使用的 plunker,配置为在选择更改时调用函数。

https://plnkr.co/edit/zOZ9Tqv4r5rYPXTNyICx?p=preview

标记:

  <body ng-app="myApp">
    <div ng-controller="myController">
      <select ng-model="selectedOption" ng-change="someFunction()">
        <option ng-repeat="device in someArray">device.name</option>
      </select>
    </div>
  </body

希望这会有所帮助。

【讨论】:

【参考方案2】:

首先我认为使用ng-value="device.id" 而不是value="device.id" 更正确(angularJS-wise!)。您也可以简单地将 $index 作为该值传递(如 ng-value="$index"),然后访问 $scope.filterMarkers 函数中的选定数据,如下所示:devicesData = $scope.data[$scope.deviceList] 而不是使用过滤器...

但除此之外,我认为问题可能来自您在响应来自服务器之后定义 $scope.devicelist 的事实。在此之前,angular 在渲染页面并看到ng-model="deviceList" 时会创建另一个变量,所以这可能是导致问题的原因。

这也可能是因为为您的页面定义了不止一次的控制器。就像用ng-controller="something"在你的html中定义它,同时将它分配给你的JS文件中的应用程序......这导致控制器功能从开始运行两次......(你可以通过放置一个控制台来测试它.log("someText") 在你的控制器中,看看它是否被记录了不止一次)

无论如何,最好的检查方法(考虑到我看不到并运行你的所有代码)可能是简单地使用 chrome 的 devtools 等工具跟踪你的代码,看看它会发生什么以及谁在调用该函数又...

希望对您有所帮助!

【讨论】:

以上是关于AngularJS:从下拉列表中选择任何选项时,函数在 ng-change 上触发两次的主要内容,如果未能解决你的问题,请参考以下文章

从自动完成下拉列表中未选择任何选项时如何清除 mat- 自动完成

基于下拉列表中选项的选择动态更新表格的Angularjs代码

从视图中的动态文本框发送数据到 AngularJS 控制器

AngularJS 中的下拉菜单

如何使已选择的选项不显示在另一个选择选项下拉 JAVASCRIPT/ANGULARJs

仅当从下拉列表中选择选项时才附加到 iframe src