Dependent选择Angular JS

时间:2015-09-25 12:04:50

标签: javascript angularjs

我有分层数据集。有一个固定的根单元。

我想要做的是使这个树可以通过依赖选择进行浏览。

我创建了一个带有固定数据集的简单plunkr示例。

http://plnkr.co/edit/Bz5A1cbDLmcjoHbs5PID?p=preview

示例中的数据格式模仿了我从服务器请求中获得的格式" real"寿命。

这个简单的第一步工作正常。缺少的是,当用户在中间的某处更改选择时,需要销毁选择框和新选择下面的ng-model绑定。

因此,当我选择Europe-> France-> Quimper并更改" Europe"到"亚洲" - 然后应该有"亚洲"作为第一个选择框,第二个是亚洲国家。

是否有" Angular"处理这个问题的方式?任何其他提示也值得赞赏;)

<!DOCTYPE html>
<html ng-app="app">

<head>
  <link data-require="bootstrap@3.3.5" data-semver="3.3.5" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
  <script src="https://code.angularjs.org/1.3.17/angular.js" data-semver="1.3.17" data-require="angular.js@1.3.17"></script>
</head>

<body>

  <div ng-controller="Ctrl">

    <select ng-repeat="select in selects track by $index" ng-model="$parent.boxes[$index]">
      <option ng-repeat="child in select.children" ng-click="expandSelects(child)">{{child.name}}</option>
    </select>


    <ul>
      <li ng-repeat="item in boxes">{{ item }}</li>
    </ul>

  </div>


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

    app.controller('Ctrl', ['$scope', function($scope) {

      var data = {
        'europe': {
          name: 'europe',
          children: [{
            name: 'france',
            parent: 'europe'
          }, {
            name: 'italy',
            parent: 'europe'
          }],
        },
        'asia': {
          name: 'asia',
          children: [{
            name: 'japan',
            parent: 'asia'
          }, {
            name: 'china',
            parent: 'asia'
          }],
        },
        'france': {
          name: 'france',
          children: [{
            name: 'paris',
            parent: 'france'
          }, {
            name: 'quimper',
            parent: 'france'
          }]
        }
      };

      var root = {
        name: 'world',
        children: [{
          name: 'europe',
          parent: 'world'
        }, {
          name: 'asia',
          parent: 'world'
        }, ]
      };

      $scope.selects = [root];

      $scope.expandSelects = function(item) {
        var select = data[item.name];
        if (select) {
          $scope.selects.push(select);
        }
      }

      $scope.$watch('boxes', function(item, old) {

      }, true);

    }]);
  </script>
</body>

</html>

3 个答案:

答案 0 :(得分:1)

这是级联下拉列表的典型示例,其中级联中未知数量的级别增加了挑战。为简单起见,我将数据集合并到一个对象中,为下拉列表添加了标签,并简化了select元素。

此解决方案允许任意数量的级别,因此如果您需要低于城市级别的数据,您可以在不更改任何代码的情况下添加它,如我添加到巴黎的“街道”示例所示。

select {
  display: block;
}
<!DOCTYPE html>
<html ng-app="app">

<head>
  <link data-require="bootstrap@3.3.5" data-semver="3.3.5" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
  <script src="https://code.angularjs.org/1.3.17/angular.js" data-semver="1.3.17" data-require="angular.js@1.3.17"></script>
</head>

<body>
  <div ng-controller="Ctrl">
      <div ng-repeat="select in selects track by $index" ng-if="select.children">
          <label>{{ select.optionType }}</label>
          <select ng-model="selects[$index + 1]" ng-options="child.name for child in select.children" ng-change="clearChildren($index)"></select>
        <hr />
      </div>
  </div>

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

    app.controller('Ctrl', ['$scope', function($scope) {
      var data = {
        optionType: 'Continent',
        name: 'World',
        children: [
          {
            optionType: 'Country',
            name: 'Europe',
            children: [
              {
                optionType: 'City',
                name: 'France',
                children: [
                  {
                    optionType: 'Street',
                    name: 'Paris',
                    children: [
                    {
                      name: 'First'
                    },
                    {
                      name: 'Second'
                    }
                  ]
                  },
                  {
                    name: 'Quimper'
                  }
                ]
              },
              {
                name: 'Italy'
              }
            ]
          },
          {
            optionType: 'Country',
            name: 'Asia',
            children: [
              {
                name: 'Japan'
              },
              {
                name: 'China'
              }
            ]
          }
        ]
      };

      $scope.selects = [data]
      $scope.clearChildren = function (index) {
        $scope.selects.length = index + 2;
      };
    }]);
  </script>
</body>
</html>

答案 1 :(得分:0)

在你的层次结构中去看孩子并不像看起来那么难。如果您设置了带有角度的选择,并让它为您做大部分选择(例如使用ng-options而不是ng-重复标记本身),并告诉它有哪些选项,那么您的孩子列表尝试渲染只是成为从上面的选择中挑选的孩子的标准ng重复。

我修改了你的plunker,向你展示如何以一种稍微不同的方式完成。

http://plnkr.co/edit/zByFaVKWqAqlR9ulxEBt?p=preview

我改变的要点是

$scope.expandSelects = function() {
    var select = data[$scope.selected.name];
    if (select) {
      console.log('changed');
      console.log(select);
      $scope.chosen = select;
    }
  }

这里我只是抓住将要使用的所选项目。然后结局看起来像。

<ul>
  <li ng-repeat="item in chosen.children">{{ item.name }}</li>
</ul>

唯一真正需要的其他设置是设置ng-options并为其提供绑定模型。

<select ng-options="child.name for child in selects.children" 
    ng-model="selected" ng-change="expandSelects()">
</select>

答案 2 :(得分:0)

使用可以使用第二个选择上的过滤器来根据先前的选择过滤de选项。

例如,您可以选择第一个选择大陆:

<select ng-options="c for c in continents" ng-model="selectedContinent" ></select>

和国家的第二个选择:

<select ng-options="c.name for c in countries | filter : {parent:selectedContinent}" ng-model="selectedCountry" ></select>

使用简化数据构建一个简化数据,以显示过滤器的工作原理:http://jsfiddle.net/marcosspn/oarL4n78/