ngSelect - 具有任意深度的嵌套选项

Ped*_*Sol 6 javascript angularjs

在我的应用程序中,我有一个具有以下结构的对象数组

[{"ID":1, "parentID":0, "name":"Parent #1"}, 
{"ID":2, "parentID":0, "name":"Parent #2"}, 
{"ID":3, "parentID":1, "name":"Child #1 1"}, 
{"ID":4, "parentID":3, "name":"child #1 2"},
{"ID":5, "parentID":2, "name":"child #2 1"},
{"ID":6, "parentID":5, "name":"child #2 2"}]
Run Code Online (Sandbox Code Playgroud)

我想将其呈现为一个选择菜单,它允许用户选择叶节点,同时仍然输出不可选择的父节点以显示结构的层次结构。

我尝试了几种方法,其中最成功的是,在我的 angular 模板中,有一些类似以下的内容。

<div ng-repeat="(idx, category) in $scope.allCats">
    <select ng-model="$scope.cats[idx]" 
            ng-options="cat as cat.name group by $scope.parentName(cat.parentID, idx) for cat in $scope.allCategories track by cat.ID">
        <option value="">Select A Category</option>
    </select>
</div>
Run Code Online (Sandbox Code Playgroud)

$scope.allCats是上面的数组,$scope.parentName()方法返回一个字符串。

下面的屏幕截图展示了这个问题的麻烦。即所有父项出现两次,一次作为 an <option>,一次作为 an <optgroup>,而我宁愿它们只作为可选项目出现,但显然它们是父项,并且不保持结构的层次结构;具有祖先和后代的子节点不会出现在正确的“家谱”结构中。

截屏

我怎样才能改变我注入的数据或我的角度模板来实现我想要的行为?

也就是说,要显示由parentID属性定义的整个层次结构,因此每个系列共享一个共同的祖先,并且父项仅出现一次。

我怀疑这很复杂,因为可能有不止一个级别的后代,因为我想尽可能地保持这种情况。

man*_*nji 2

在将数组传递给角度模板之前对范围内的数组进行排序怎么样?如果你有:

var arr = [
  {"ID":1, "parentID":0, "name":"Parent #1"}, 
    {"ID":3, "parentID":1, "name":"Child #1 1"}, 
      {"ID":4, "parentID":3, "name":"child #1 2"},
        {"ID":7, "parentID":4, "name":"asdfadsf"},
  {"ID":2, "parentID":0, "name":"Parent #2"}, 
    {"ID":5, "parentID":2, "name":"child #2 1"},
      {"ID":6, "parentID":5, "name":"child #2 2"}
];
Run Code Online (Sandbox Code Playgroud)

会更容易。只需按原样显示即可。

排序代码:

var sortKeys = {};

// computes a unique sort key
function getSortKey(item) {
  if(sortKeys[item.ID] === undefined) {
    var parentItem = arr.filter(function(it) {
      return it.ID === item.parentID;
    })[0];

    if(parentItem != null) {
      return getSortKey(parentItem)  + '' + item.ID;
    }

    return item.parentID + '' + item.ID;
  }

  return sortKeys[item.ID];
}

// build sort keys to be used to sort items following their hierarchy
arr.forEach(function(item) {
  sortKeys[item.ID] = getSortKey(item);
});

// sort the array
arr.sort(function(item1, item2) {    
  var item1SortKey = sortKeys[item1.ID],
      item2SortKey = sortKeys[item2.ID];

  return item1SortKey < item2SortKey ?
    -1 :
    (item1SortKey > item2SortKey ?
      1:
      0);
});
Run Code Online (Sandbox Code Playgroud)

var arr = [
  {"ID":1, "parentID":0, "name":"Parent #1"}, 
    {"ID":3, "parentID":1, "name":"Child #1 1"}, 
      {"ID":4, "parentID":3, "name":"child #1 2"},
        {"ID":7, "parentID":4, "name":"asdfadsf"},
  {"ID":2, "parentID":0, "name":"Parent #2"}, 
    {"ID":5, "parentID":2, "name":"child #2 1"},
      {"ID":6, "parentID":5, "name":"child #2 2"}
];
Run Code Online (Sandbox Code Playgroud)
var sortKeys = {};

// computes a unique sort key
function getSortKey(item) {
  if(sortKeys[item.ID] === undefined) {
    var parentItem = arr.filter(function(it) {
      return it.ID === item.parentID;
    })[0];

    if(parentItem != null) {
      return getSortKey(parentItem)  + '' + item.ID;
    }

    return item.parentID + '' + item.ID;
  }

  return sortKeys[item.ID];
}

// build sort keys to be used to sort items following their hierarchy
arr.forEach(function(item) {
  sortKeys[item.ID] = getSortKey(item);
});

// sort the array
arr.sort(function(item1, item2) {    
  var item1SortKey = sortKeys[item1.ID],
      item2SortKey = sortKeys[item2.ID];

  return item1SortKey < item2SortKey ?
    -1 :
    (item1SortKey > item2SortKey ?
      1:
      0);
});
Run Code Online (Sandbox Code Playgroud)