【问题标题】:AngularJS: ngRepeat for select on change ngOptions-listAngularJS:ngRepeat 用于在更改 ngOptions-list 时进行选择
【发布时间】:2015-07-27 04:48:42
【问题描述】:

我有一个 angularjs 应用程序,它有一个使用 ngOptions 填充了数组选项的选择。每次用户单击按钮添加一个时,ngRepeat 指令都会在底部生成一个新的选择。

我想确保用户不能选择重复的值。

所以如果我的列表包含 3 个项目:Item1、Item2 和 Item3,并且用户选择 Item3 然后按下按钮,最后生成的选择列表应该只包含项目“Item1”和“Item2”。 如果用户随后选择“Item1”并按下按钮,用户应该会看到仅使用“Item2”选项生成的下一个选择。

所以一般来说,在上面的例子中,生成的 HTML 应该是这样的:

<div data-ng-repeat="item in selectedOptions">
  <select>
    <option value="1">Item1</option>
    <option value="2">Item2</option>
    <option value="3">Item3</option>
  </select>

 <select>
  <option value="1">Item1</option>
  <option value="2">Item2</option>
 </select>

 <select>
  <option value="2">Item2</option>
 </select>
</div> 

请记住:用户将一直看到所有三个选项,一次是每个选项都可用,一次是只有两个选项可用,一次是只有一个选项可用。

我一直在想很多方法来完成这项工作,但到目前为止我还没有运气。有谁知道我可以在角度中使用的模式来实现这种行为?

这是我迄今为止尝试过的。

<div data-ng-repeat="function in item.Functions">
    <select data-ng-model="function.Id" data-ng-options="j.Id as j.Name for j in getCorrectFunctions(functionsList)">
        <option selected="selected" value="">---</option>
     </select>

     <a data-ng-click="addFunction()">
        <i class="fa fa-plus fa-plus-lower"></i>
     </a>
</div>

在我的指令代码中,我有以下功能:

  function getCorrectFunctions(functionList) {
                var item = scope.item;

                var list = functionList.slice();

                //excluded for brevity: this was a loop which would remove every item that wasn't available anymore

                return list;
            }

我认为这将对列表中的每个项目执行一次,但似乎并非如此。 我不认为应用过滤器会有什么不同,不是吗?

【问题讨论】:

  • 您能否再展示一些到目前为止您已经完成的代码,例如创建一个 jsfiddle/plunker?根据您到目前为止所做的事情,一种方法可能是在您的data-ng-repeat 上使用自定义过滤器,这将过滤掉那些已经选择的选项。另一个可能是在生成新的selectedOptions 数组时预先进行过滤。
  • 我已经更新了我的问题以包含我尝试过的一些事情
  • 我不确定我是否完全理解您要实现的目标...初始状态是否是您的函数数组中有 3 个项目,并且您想显示 3 个选择分别有 3、2 和 1 个选项?这将如何防止您的用户两次选择相同的选项,例如在您的第一次和最后一次选择中?
  • 你是对的,它实际上并没有阻止我的用户选择相同的选项两次。还没有想到这种可能。你能想出一种方法,让所有的选择只显示可以使用的数据吗?例如,使用过滤器?因为第一次选择要一直显示选中的函数,而不能显示其他选择中已经选中的函数……这才是我脑子里真正空白的地方。
  • 我会说是的,过滤器应该在那里工作。您需要将用户选择保存在某处(由选择索引,因此您将知道在哪里选择了哪个选择 -> 不要过滤掉),然后在过滤器功能中过滤掉那些已经选择的。

标签: javascript html angularjs


【解决方案1】:

以下是对此的一种看法。这不支持动态添加新功能,但它确实阻止用户选择任何给定项目两次。

有关工作示例和更多详细信息,请参阅 Plunker

首先是 Angular 设置部分。在这里,我定义了一个函数对象的模拟数组 ($scope.functions) 和用于用户选择的数组 ($scope.selected)

var app = angular.module('app', []);

app.controller('SelectCtrl', function ($scope) {
  $scope.functions = [
    {id: 1, name: 'First'},
    {id: 2, name: 'Second'},
    {id: 3, name: 'Third'},
  ];
  $scope.selected = [];

  $scope.selectedFilter = function (selectNumber) {
    // snipped for now
  };
});

在 html 中,仅显示一个选择,但对所有 3 个选择使用类似的方法:将所选值设置为给定索引中的 selected 数组(0 用于下面显示的情况),并使用 selectedFilter 来用相同的索引值过滤functions

  <select ng-options="j.id as j.name for j in functions | filter:selectedFilter(0)" ng-model="selected[0]">
    <option value="" selected="selected">---</option>
  </select>

最后是过滤功能。它为所有未选择的函数返回true为给定选择的选定函数。

  $scope.selectedFilter = function (selectNumber) {
    return function (func) {
      if ($scope.selected.length === 0) {
        return true;
      } else {
        var unselectedFunctions = _.filter($scope.functions, function (fn) {
          return _.findIndex($scope.selected, function (sel) {
            return fn.id === sel;
          }) === -1;
        });
        var selectedForCurrentId = $scope.selected[selectNumber];
        var selectedForCurrent = _.find($scope.functions, {id: selectedForCurrentId});
        return func === selectedForCurrent || _.findIndex(unselectedFunctions, {id: func.id}) > -1;
      }
    };
  };

在这里,我使用了Lodash 来实现一些不错的辅助功能。与 Lodash 没有任何关联,但我真的建议你看看它,或者任何其他类似的库。

希望这可以帮助您继续前进!

【讨论】:

  • 这看起来是一个很好的解决方案,非常感谢。 Lodash 的链接也非常感谢,因为我还没有听说过!明天我会尝试实施你的解决方案,所以如果它成功了,我会告诉你的。我是否正确假设所有以下划线开头的函数(如_.findIndex)都是Lodash函数?
  • 是的,所有 _. 函数都来自 Lodash。文档非常好,你不应该对它们有任何问题。希望这对您有所帮助,如果还有其他问题,请告诉我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多