【问题标题】:Angular. Send http requests after selecting checkboxes角。选中复选框后发送 http 请求
【发布时间】:2015-02-18 15:31:42
【问题描述】:

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

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

问题: 所以每次用户选择或取消选择一个来源时,都应该向服务器发送一个http请求,并且应该更新文章列表。

我的问题是,我不确定如何调用将发送 http 请求的函数(在下面的代码 sn-ps 中,它被称为 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) 如果我将函数绑定到input 标签上的ng-change

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

【问题讨论】:

  • 好问题:很好的目​​标和问题
  • @NewDev 是对的,你能发布你的 selectAll 代码吗?
  • @azangru,您需要只提交更改的来源,还是只重新提交所有选定的来源(即使只选择了 1 个额外的来源)?
  • @NewDev:我还不太确定。目前,我正在重新提交所有来源列表,指出哪些被选中(selected=true),哪些未被选中。一定是浪费带宽:-(

标签: javascript angularjs


【解决方案1】:

你应该使用ng-change

ng-change 仅在输入更改模型时触发 - 而不是相反。您的 selectAll 应该更改模型。我猜您正在以不同的方式执行“全选”。

$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>

【讨论】:

  • 这很有趣。我想我还没有仔细研究 ng-change 选项。我会去看看它是否给我带来了我认为它会给我带来的问题,或者这是否完全是我的想象。
  • 嘿,你是对的。看来我是担心太多了,在指令中做$scope.sources[i].selected = true;之类的操作不会触发ng-change。棒极了!让我重新编写我的指令,看看是否有任何问题:-)
  • 耶!像魅力一样工作。
  • @azangru,是的,这是“设计使然”。 ng-change 旨在更新更改的控制器。如果控制器本身更改模型值,则控制器不需要额外的触发器。
【解决方案2】:

我更喜欢你的第一个解决方案,在四处探索后我想起了一个类似的问题: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/

【讨论】:

  • 非常简单干净 - 很棒
  • @BenDiamant - 一点也不干净! Mathew,你的控制器现在知道 View - 它应该是 View-agnostic
  • @NewDev 你对它太严格了,如果它是一个重复的逻辑,在指令中执行(一个批准的选项)但如果不是控制器是好的。
  • @BenDiamant,不,不......这表明对 MVVM 的错误思考比意识到视图的特定实例更重要。不能太严格
  • 我选择了@NewDev 的答案,但我只是想说谢谢你展示了另一种有趣的方法来解决这个问题。
【解决方案3】:
<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(button/Link) 有多种方法可以使用....

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

【讨论】:

    猜你喜欢
    • 2023-03-12
    • 1970-01-01
    • 2019-05-09
    • 1970-01-01
    • 2012-04-20
    • 1970-01-01
    • 2016-12-15
    • 1970-01-01
    • 2016-11-01
    相关资源
    最近更新 更多