0

我对 AngularJS 非常陌生,在观看了一些复数视频后,我决定使用它构建一个简单的网页。

该页面最初应该加载一个由 ajax 请求填充的选择框(这包含所有数据)。然后,根据选择的值,可能需要创建一个包含子数据的新选择元素。这将继续发生,直到选择没有子 ID 的选项。我从 api 返回的数据格式如下。

[ { "ChildIds" : [  ],
    "Id" : "1",
    "Name" : "Top Level",
    "ParentId" : null
  },
  { "ChildIds" : [ "51" ],
    "Id" : "22",
    "Name" : "LevelA - 1",
    "ParentId" : "1"
  },
  { "ChildIds" : [ "38",
        "26"
      ],
    "Id" : "24",
    "Name" : "LevelA - 2",
    "ParentId" : "1"
  },
  { "ChildIds" : [  ],
    "Id" : "38",
    "Name" : "LevelB - 1",
    "ParentId" : "24"
  },
  { "ChildIds" : [  ],
    "Id" : "26",
    "Name" : "LevelB - 2",
    "ParentId" : "24"
  },
  { "ChildIds" : [  ],
    "Id" : "51",
    "Name" : "LevelB - 3",
    "ParentId" : "22"
  },
  { "ChildIds" : [ "43",
        "21"
      ],
    "Id" : "36",
    "Name" : "LevelC - 1",
    "ParentId" : "26"
  },
  { "ChildIds" : [  ],
    "Id" : "43",
    "Name" : "LevelD - 1",
    "ParentId" : "36"
  },
  { "ChildIds" : [  ],
    "Id" : "21",
    "Name" : "LevelD -2",
    "ParentId" : "36"
  }
]

我已经设法通过使用硬编码的选择元素来完成这项工作,但想让它变得动态。

html

<div class="container">
        <div ng-controller="organisationalUnitCtrl">
            <select class="form-control" ng-model="root" ng-options="ou.Name for ou in ous | filter:{ParentId:'!'}">
                <option value="">-- choose organisation unit --</option>
            </select>
            <select class="form-control" ng-model="child" ng-options="ou.Name for ou in ous | filter:{ParentId:root.Id}">
                <option value="">-- choose organisation unit --</option>
            </select>
            <select class="form-control" ng-model="child2" ng-options="ou.Name for ou in ous | filter:{ParentId:child.Id}">
                <option value="">-- choose organisation unit --</option>
            </select>
            <select class="form-control" ng-model="child3" ng-options="ou.Name for ou in ous | filter:{ParentId:child2.Id}">
                <option value="">-- choose organisation unit --</option>
            </select>
        </div>
    </div>

控制器

bristowRiskApp.controller('organisationalUnitCtrl',
    function organisationalUnitCtrl($scope, organisationalUnitData) {
        $scope.ous = organisationalUnitData.getOrganisationalUnit();
    }
);

服务

bristowRiskApp.factory('organisationalUnitData', function ($http, $q) {
    return {
        getOrganisationalUnit: function () {
            var deferred = $q.defer();

            $http({ method: 'GET', url: 'http://localhost:53995/api/organisationalunit' }).
                success(function (data, status, headers, config) {
                    deferred.resolve(data);
                }).
                error(function (data, status, headers, config) {
                    deferred.reject(status);
                });

            return deferred.promise;
        }
    }
});

我读过你不应该在控制器中操作 DOM。所以,我猜我应该为我的 select 元素创建一个指令,监听 onChange 事件并创建新的 select 元素?我该怎么做呢?有没有可以借鉴的例子?

我在硬编码示例中面临的另一个问题是,更改选择中的值只会影响下一个组合。例如,如果在所有四个选择框中都选择了值,则更改第二个选择框中的值将正确重置第三个框,但第四个框仍将包含所选选项。我认为这种变化会一直波及下去。

谢谢

史蒂文

4

1 回答 1

1

如果/为什么这不起作用,请告诉我,我会相应地修复它。我认为关键事实是在选项中继器中,您没有使用语法来指定选项的 ID - 您只是在做它的标签。

http://jsfiddle.net/KVdqb/

HTML

<div ng-app="bristowRiskApp" ng-controller="organisationalUnitCtrl">
    $scope.selections: <pre>{{ selections | json }}</pre>
    <div ng-repeat="i in range(selections.length - 1)">
        <cascade-select data="data" parent-id="selections[i]" selected-id="selections[i + 1]"></cascade-select>
    </div>
</div>

Javascript

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

bristowRiskApp.controller('organisationalUnitCtrl',

function organisationalUnitCtrl($scope) {
    $scope.data = [ /* ... */ ];

    $scope.selections = [ null, null ];

    $scope.$watch('selections', function (value) {
        if (value[value.length - 1] !== null || value.length < 2) {
            value.push(null);
        } else {
            var index = value.indexOf(null, 1);
            if (0 < index && index < value.length - 1) {
                $scope.selections = value.slice(0, index);
            }
        }

    }, true);

    // Helper function.    
    $scope.range = function (n) {
        var result = [];

        for (var i = 0 ; i <n; i++) {
            result.push(i);
        }

        return result;
    };
});

bristowRiskApp.directive('cascadeSelect', function () {
    return {
        restrict: 'E',
        replace: true,
        scope: {
            parentId: '&',
            selectedId: '=',
            data: '='
        },
        template: '<select ng-show="(data | filter:byId).length > 0" ng-model="selectedId" ng-options="d.Id as d.Name for d in data | filter:byId"><option value="">-- choose organisation unit --</option></select>',
        link: function (scope, element, attrs) {
            scope.byId = function (d) {
                return d.ParentId === scope.parentId();
            };
        }
    }
});
于 2013-09-13T16:00:03.863 回答