在angular.js中创建一个级联的Dropbox

时间:2013-12-07 09:15:01

标签: javascript angularjs

我有一个嵌套对象,我试图将其变成级联选择框。

    "A": {
      "a1": 1,
      "a2": 2
    },
    "B": {
      "b1": {
        "b11": 111
      },
      "b2": {
        "b222": 222
      }
    }
  };

用户应该选择值,直到达到某个值。收集的深度未知。

例如 - "B" - > "b1" - > "b11" - > 111。在这种情况下,我们有三个选择框。 "A" - > "a1" - > 1 - 只有两个。在上一级别中选择一个值后,每个框都会出现。

我用模板试了一下(从红色开始,这是实现递归的唯一方法)。我需要scope.value的最终值。

<script type="text/ng-template" id="cascading_combo.html">
    <h5> current </h5>
    <pre>{{current | json}}</pre>
    <select ng-model='value' ng-options="v as k for (k,v) in current"></select>
    <pre> type of {{value}} : {{angular.isObject(value)}}</pre>
    <span ng-if="angular.isObject(value)" ng-init='current=value' ng-include='"cascading_combo.html"'>
    </span>
</script>

这不起作用,因为angular.isObject没有返回任何结果。

JSBIN playgorund.

Angular newbi,感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

您无法在类似的表达式中调用angular.isObject()。 Angular当时正在寻找的是父控制器范围内的函数$scope.angular.isObject()(正如value确实是$scope.value)。

你可以做的是:

selectCtrl

$scope.isObject = angular.isObject;

cascading_combo.html

<pre> type of {{value}} : {{isObject(value)}}</pre>
<span ng-if="isObject(value)" ng-init='current=value' ng-include='"cascading_combo.html"'>

问题:您遇到无限循环。

如果value是对象,则会再次加载模板。所有这些模板都存在于selectCtrl的相同范围内,因此当附加新模板时value 仍然一个对象,因此附加了另一个模板,等......

为了防止这种情况,您必须在添加新模板时重置value。例如,您可以再次修改模板并执行此操作:

<select ng-init="value=undefined" ng-model="value" ng-options="k for (k,v) in current"></select>

有关最终结果,请参阅here


更新

上面的示例不能以动态方式工作,因为一旦添加了模板,就无法删除它。以下是使用ngRepeat和单个列表的非重复方法:

HTML

<div ng-app="app" ng-controller="ctrl">
     <div recoursive-select="" ng-repeat="item in selected"></div>
</div>

JS

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

app.controller('ctrl', function($scope) {
    $scope.selected = [/** insert first element here **/];
});

app.directive('recoursiveSelect', function() {
    return {
        template: '<select ng-model="newSelected" ng-options="key for (key, value) in data"></select>',
        controller: function($scope) {
            // workaround to strip the $$hashKey of ngRepeat
            $scope.data = angular.fromJson(angular.toJson($scope.item));
            // watch for selecting a value
            $scope.$watch('newSelected', function(newSelected) {
                // watch is always called initially. do this to prevent infinite loop
                if (!newSelected) return;
                var nextIndex = $scope.$index + 1;
                // remove all "deeper" elements plus the one on this level
                while ($scope.selected.length > nextIndex) {
                    $scope.selected.pop()
                }
                // add the newly selected element on this level
                $scope.selected.push(newSelected);
            });
        }
    };
});

live