Angularjs -在选择字段中设置用户选择的限制

Angularjs - set limit on user choice in a select field

本文关键字:选择 用户 设置 字段 Angularjs      更新时间:2023-09-26

我试图构建一个方法来限制用户在几个选择字段中的选择。下面是一个示例,这里是一个jsfiddle - http://jsfiddle.net/HB7LU/18414/

HTML:

<div ng-controller="MyCtrl">
  <select size="5" id="selectpicker1" multiple ng-model="params.monthly" ng-change="selectionChanged(params.monthly)">
     <option ng-repeat="month in newMonthlyArray">{{month}}</option>
  </select>
</div> 

控制器:

var myApp = angular.module('myApp', []);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl($scope) {
    $scope.name = 'Superhero';
    //console.log('YES');
    $scope.newMonthlyArray = ["2015-Jan", "2015-Feb", "2015-Mar", "2015-Apr"];
    $scope.selectionChanged = function (data) {
        if (data.length > 2) {
            alert('You can choose 2 months');
        }
    }
}

我遇到问题的部分是删除最后选择的选项并更新$scope变量。我可以使用JQuery,但不想创建一个混合解决方案。

任何想法都将非常感激!

您不需要做那么多来删除额外的选定元素:

if(data.length > 2){
    data.splice(2);
    //alert('You can choose 2 months');
}

基本上,这就是你所需要的:data是你的ng-model="params.monthly"因为这个模型被绑定到select元素,Angular会做剩下的事情来更新它:

http://jsfiddle.net/HB7LU/18420/

编辑:正如@Metallica所建议的,并不是在所有情况下,select元素都会被Angular更新。

提供视觉反馈的唯一方法是手动更新DOM:
if(data.length > 2) {
    data.splice(2);
    var selected = select.querySelectorAll('option:checked');
    angular.forEach(selected, function(s) {
        if(data.indexOf(s.value) < 0) s.selected = false;
    });
}

更新后的示例中,select$element[0].querySelector('select')这个控制器中的select元素。

附加代码是:

  • 获取所有选中的选项元素和
  • 遍历元素并检查它们是否存在于模型数据中,并相应地更新selected属性

更新小提琴:http://jsfiddle.net/HB7LU/18422/

您可以在select元素中获得额外选中项的引用,并取消选中这些项。在您的selectionChanged方法中,迭代select元素中的选项,取消选择无效的选项,并更新您的模型(data是对params.monthly的引用)。

angular.forEach(document.getElementById("selectpicker1").options, function(item) {
  if (data.length > 2 && item.selected) {
    data.splice(2);
    item.selected = false;
  }
});

你可以使用$watch服务使事情变得更容易,并删除自己的监视方法(selectionChanged):

$scope.$watch(function() {
  // In this function, return whatever object/value you would like to observe. 
  // This function is invoked whenever there is a change to the specified value/obj
  return document.getElementById("selectpicker1").options;
}, function (items) {
  // The argument of this function holds the new value of what you return in the 
  // first function. Feel free to name it whatever you wish
  angular.forEach(items, function(item) {
    var data = $scope.params.monthly;
    if (data.length > 2 && item.selected) {
      data.splice(2);
      item.selected = false;
      alert('You can choose 2 months');
    }
  });
});

通常你需要清理/注销你的watch函数,但在这种情况下,你不需要这样做,因为没有其他方法/函数依赖于你的select元素的值

使用ng-options。见我的叉子

<select (...) ng-options="month for month in newMonthlyArray">

在控制器中,删除最后选中的(使用lodash):

if(data.length > 2){
  alert('You can choose 2 months');
  data = _.pull(data, _.last(data))
}

添加到控制器:

$scope.onSelect = function() {
    var selected = this.month;
    $scope.newMonthlyArray.splice($scope.newMonthlyArray.indexOf(selected), 1);
};

和这个到你的标签:

<option ng-click="onSelect()" ...