角。选中复选框后发送http请求

时间:2015-02-18 15:31:42

标签: javascript angularjs

背景 我正在开发一个显示文章列表的角度应用程序。可以通过各种设置修改列表。一个这样的设置是这些文章的来源。将来源视为新闻机构:文章来自特定来源:

enter image description here

因此,当用户点击“来源”链接时,会出现一个下拉菜单,其中包含来源列表。用户可以选择这些来源的任何组合。还有一个“全选”和“全部清除”按钮可以选择所有来源或取消全部:

enter image description here

问题: 因此,每次用户选择或取消选择源时,都应该将http请求发送到服务器,并且应该更新文章列表。

我的问题是,我不知道如何调用将发送http请求的函数(在其下面的代码片段中称为updateArticleList())。

1)如果我将函数绑定到ng-click并将其设置在label标记上:

<ul>
  <li ng-repeat="source in sources">
    <label ng-click="updateArticleList()">
      <input type="checkbox" ng-model="source.selected">
      {{source.title}}
    </label>
  </li>
</ul>

然后点击标签会触发该功能两次(一次用于label,显然,一次用于input)。不好。

2)如果我将函数绑定到ng-change标记上的input

<ul>
  <li ng-repeat="source in sources">
    <label>
      <input type="checkbox" ng-model="source.selected"
       ng-change="updateArticleList()">
      {{source.title}}
    </label>
  </li>
</ul>

然后,一旦我点击“全选”或“清除”按钮,这将改变所有复选框的状态并发送大量的http请求。也不好。

现在,我正在尝试使用setTimeout来解决这个问题,以便过滤掉对函数的一连串调用,就像这样(通过ng-click调用函数的示例):

    var requestAllowed = true;

    var debounceRequests = function(){
      requestAllowed = false;
      setTimeout(function(){
        requestAllowed = true; 
      }, 5);
    };

    scope.updateArticleList = function(){
      if (requestAllowed === true){
        // prevent the second call to the function from ng-click
        debounceRequests();
        // also, give time for the input to register ng-click on the label
        setTimeout(function(){
             // finally, send an http request
             getArticles();
        }, 5);
      }
    };

但这看起来很脏。

所以,我的问题是,在这种情况下发出http请求的好方法是什么?

最好不要使用额外的js库。

==================

更新:

这是由“全选”触发的功能:

    scope.selectAllSources = function(){
      scope.sources.forEach(function(source){
        source.selected = true;
      });
      scope.updateArticleList();
    };

3 个答案:

答案 0 :(得分:2)

您应该使用ng-change

ng-change仅在输入更改模型时触发 - 而不是相反。您的selectAll应该更改模型。我猜你正在做&#34;选择全部&#34;不同。

$scope.selectAll = function(){
  for (var i = 0; i < $scope.sources.length; i++) {
    $scope.sources[i].selected = true; // this does not fire `ng-change`
  }

  $scope.updateArticleList();
}

编辑:根据OP关于每次更改提交所有来源的评论,以下是如何实现这一目标的更完整的概念示例:

<li ng-repeat="source in sources">
   <label>
      <input type="checkbox" ng-model="source.selected" ng-change="updateArticleList()">
      {{source.title}}
   </label>
</li>
<button ng-click="selectAll()">select all</button>

答案 1 :(得分:1)

我更喜欢你的第一个解决方案,在探索后我记得一个类似的问题:Angular.js ng-click events on labels are firing twice

因此,您可以做的解决方法是检查事件元素并确保标记正确。

    $scope.updateArticleList = function(event){
        if(event.toElement.tagName == 'LABEL'){
            //run code
        }
    };

HTML

<label ng-click="updateArticleList($event)">

JSFiddle:http://jsfiddle.net/4p48q63j/

答案 2 :(得分:0)

<ul>
  <li ng-repeat="source in sources">
    <label>
      <input type="checkbox" ng-model="source.selected"
       ng-change="updateArticleList(source.selected)">
      {{source.title}}
    </label>
  </li>
</ul>

控制器; 个人选择......

$scope.updateArticleList=function(checked)
{
    if(checked==true)
    {
      //Call to service
    }
}

对于selecteAll(按钮/链接),有多种方式可以使用....

    $scope.selectAll = function(){
    angular.forEach($scope.sources,function(source,$index){
       // model value will be true for all sources....
       //Call to service
    });
    };