带有父子组合的动态表单

时间:2013-08-28 15:03:30

标签: angularjs

我是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元素?我该怎么做呢?有没有可以向我学习的例子?

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

由于

史蒂芬

1 个答案:

答案 0 :(得分: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();
            };
        }
    }
});