角度自定义多选列表

时间:2014-08-10 20:16:56

标签: javascript angularjs angularjs-directive

我想构建一个列表,其功能类似于给定参数的select或multiselect。例如。如果参数为false,请选择A->选择B,取消选择A并选择B.

 <ul>
      <li>a,</li>
      <li>b, and</li>
      <li>c</li>
</ul>

我最初的方法看起来像:

<ul myDirective>
      <li ng-model="a">a,</li>
      <li ng-model="b">b, and</li>
      <li ng-model="c">c</li>
</ul>

mydirective监视LI的点击。单击它确定是否需要取消选择或取消设置任何内容。然后选择新值an并应用选定的类。

我不认为我遵循了有棱有角的范式,我正在寻找一些帮助,找到正确的前进道路。

**编辑** 我希望提供以下用户体验:http://jsfiddle.net/qbt2myj8/

2 个答案:

答案 0 :(得分:2)

在我看来,自已使用AngularJS后,自定义指令将使您的代码更加干净。

以下是使用AngularJS Custom Directive的完整解决方案,该指令完全可以重复用于代码组织。

<强> HTML

自定义指令默认行为

<ul data-my-directive class="list">
    <li>a</li>
    <li>b</li>
    <li>c</li>
</ul>

(这只是截图预览。请参阅下面的PLAYGROUND链接进行播放)

Example 1


<强> HTML

使用自定义属性

<ul data-my-directive data-multi-select="true" class="list">
    <li>a</li>
    <li>b</li>
    <li>c</li>
</ul>

(这只是截图预览。请参阅下面的PLAYGROUND链接进行播放)

Example 2


<强>的Javascript

angular.module('app',[])
  .directive('myDirective', function(){
    return {
      transclude: true,
      template: '<div ng-transclude></div>',
      link: function(scope, element, attrs){
        function addClickListener(i, callback){
          selections[i].addEventListener('click', function(){
            callback(i);
          }, false);
        }

        // Set up attribute value. Goes to default if attribute is not set up
        attrs.multiSelect = attrs.multiSelect || 'false';

        scope.isSelected = [];

        var selections = element[0].getElementsByTagName('li');

        if(attrs.multiSelect === "true"){
          for(var i = 0; i < selections.length; i++){
            scope.isSelected[i] = false;
            addClickListener(i, function(i){
              if(scope.isSelected[i] === true){
                // if previously it is selected (red color), now make it unselected (black color / default color)
                angular.element(selections[i]).removeClass('selected');
                scope.isSelected[i] = false; 
              } else {
                // previously black color, so change it to red color
                angular.element(selections[i]).addClass('selected');
                scope.isSelected[i] = true;
              }
            });
          }
        } else {
          var currentSelection = -1;
          for(var i = 0; i < selections.length; i++){
            scope.isSelected[i] = false;
            addClickListener(i, function(i){
              if(scope.isSelected[i] === true){
                // do nothing
              } else {
                // previously black color, so change it to red color
                angular.element(selections[i]).addClass('selected');
                scope.isSelected[i] = true;

                angular.element(selections[currentSelection]).removeClass('selected');
                scope.isSelected[currentSelection] = false;
                currentSelection = i;
              }
            });
          }
        }
      }
    }
  });

最后,终极

PLAYGROUND

玩耍!

我希望它能清除你的要求。祝你有愉快的一天:)

答案 1 :(得分:1)

我的方法(首先)根本不是制定指令,而是自定义JavaScript数据结构。我想到的简单例子:

/**
 * Makes a selector data structure
 * @param items elements to be listed
 * @param multi whether multiple selection is supported
 * @returns {{cells: *, selectedItems: selectedItems, unselectAll: unselectAll}}
 */
function makeSelector (items, multi) {

  var cells = items.map(function (item) {
    // each cell wraps an item and a selected flag
    return  {
      item: item,
      selected: false
    };
  });

  // returns an array of the currently selected items
  function selectedItems() {
    return cells
      .filter(function (cell) {
        return cell.selected;
      })
      .map(function (cell) {
        return cell.item;
      });
  }

  // unselects all items
  function unselectAll() {
    cells.forEach(function (cell) {
      cell.selected = false;
    })
  }

  // adding methods to cells
  cells.forEach(function (cell) {
    cell.selectMe = (multi
      ? function () {
      cell.selected = true;
    }
      : function () {
      unselectAll();
      cell.selected = true;
    });
    cell.unselectMe = function () {
      cell.selected = false;
    };

    cell.toggle = function () {
      if (cell.selected) {
        cell.unselectMe();
      } else {
        cell.selectMe();
      }
    }
  });

  return {
    cells: cells,
    selectedItems: selectedItems,
    unselectAll: unselectAll
  };
}

这样您就可以轻松检索控制器中所选项目的列表:

// ...
$scope.abcSelector = makeSelector(['A','B','C'],false);
var getSelectedItems = $scope.abcSelector.selectedItems; // to do something with them in your controller
// ...

然后使用Angular数据绑定在HTML中反映这种数据结构:

    <h3>List of items :</h3>
    <ul>
        <li ng-repeat="cell in abcSelector.cells" ng-click="cell.toggle()"
            ng-class="{'active': cell.selected}">
            {{cell.item}}
        </li>
    </ul>

    <h3>List of selected items :</h3>
    <ul>
        <li ng-repeat="item in abcSelector.selectedItems()">
            {{item}}
        </li>
    </ul>

如果你喜欢它会在指令中考虑到这一点,这通常会将所选项目的列表绑定到ng-model