Multilevel grouping in linq js

531 Views Asked by At

I have this json Format

var personArray = 
[
    {name:"person1",code:"101011",mainDept:"mainD 1",dept:"dept1",SubDept:"Sub01"},
    {name:"person2",code:"201012",mainDept:"mainD 1",dept:"dept1",SubDept:"Sub11"},
    {name:"person3",code:"301013",mainDept:"mainD 1",dept:"dept2",SubDept:"Sub12"},
    {name:"person4",code:"401014",mainDept:"mainD 1",dept:"dept2",SubDept:"Sub12"},
    {name:"person5",code:"501015",mainDept:"mainD 1",dept:"dept2",SubDept:"Sub13"},
    {name:"person6",code:"601116",mainDept:"mainD 1",dept:"dept3",SubDept:"Sub21"},
    {name:"person7",code:"701117",mainDept:"mainD 1",dept:"dept3",SubDept:"Sub21"},
    {name:"person8",code:"801118",mainDept:"mainD 1",dept:"dept4",SubDept:"Sub22"},
    {name:"person9",code:"901119",mainDept:"mainD 2",dept:"dept12",SubDept:"Sub23"},
    {name:"person10",code:"101111",mainDept:"mainD 2",dept:"dept12",SubDept:"Sub24"},
    {name:"person12",code:"121012",mainDept:"mainD 2",dept:"dept13",SubDept:"Sub25"},
    {name:"person13",code:"131013",mainDept:"mainD 2",dept:"dept131",SubDept:"Sub26"},
    {name:"person14",code:"141014",mainDept:"mainD 3",dept:"dept132",SubDept:"Sub27"},
    {name:"person15",code:"151015",mainDept:"mainD 3",dept:"dept132",SubDept:"Sub27"},
    {name:"person16",code:"161116",mainDept:"mainD 4",dept:"dept141",SubDept:"Sub1"},
    {name:"person17",code:"171117",mainDept:"mainD 4",dept:"dept141",SubDept:"Sub1"},
    {name:"person18",code:"181118",mainDept:"mainD 4",dept:"dept141",SubDept:"Sub1"},
    {name:"person21",code:"211012",mainDept:"mainD 4",dept:"dept141",SubDept:"Sub1"},
    {name:"person22",code:"221013",mainDept:"mainD 4",dept:"dept141",SubDept:"Sub001"},
    {name:"person23",code:"231014",mainDept:"mainD 4",dept:"dept151",SubDept:"Sub002"},
    {name:"person24",code:"241015",mainDept:"mainD 5",dept:"dept161",SubDept:"Sub003"},
    {name:"person25",code:"251116",mainDept:"mainD 5",dept:"dept161",SubDept:"Sub003"},
    {name:"person26",code:"261117",mainDept:"mainD 5",dept:"dept161",SubDept:"Sub003"},
    {name:"person27",code:"271118",mainDept:"mainD 5",dept:"dept161",SubDept:"Sub003"},
    {name:"person28",code:"281119",mainDept:"mainD 5",dept:"dept161",SubDept:"Sub003"},
    {name:"person29",code:"291119",mainDept:"mainD 5",dept:"dept161",SubDept:"Sub003"}];

and i want to build data for jsTree (https://www.jstree.com/docs/json/)
multi level grouping will be like this i.e mainDept -> dept - > SubDept - > person

i tried this to get one level grouping but cant figure out how to get multi level grouping.

var linq = Enumerable.From(personArray);
var grp = linq.GroupBy("$.mainDept","{text:$.dept}","{name:$,children:$$.ToArray()}").ToArray()
2

There are 2 best solutions below

0
On BEST ANSWER

There really isn't a nice way to an arbitrarily deeply nested grouping, particularly if you need to do something different at each level. Doing some sort of recursion makes this simple. Fortunately Linq.js has a Let() function to allow for this. With some specially crafted functions, this could be done rather nicely.

function grouper(propertyName, selector) {
  return function (e) {
    return e.GroupBy("$." + propertyName, null, function (k, g) {
      return {
        text: k,
        children: g.Let(selector).ToArray()
      };
    });
  };
}
var items = Enumerable.From(personArray)
  .Let(grouper('mainDept', function (g1) {
    return g1.Let(grouper('dept', function (g2) {
      return g2.Let(grouper('SubDept', function (g3) {
        return g3.Select("$.name").ToArray();
      }));
    }));
  }))
  .ToArray();

fiddle


For a different approach, you utilize jstree's alternate form of coming up with the parent/child relationships. You don't need to nest anything anymore, just come up with a flat list of the config nodes.

var items = Enumerable.From(personArray)
  .Let(function (e) {
    var roots = { '#': {}, mainDept: {}, dept: {}, SubDept: {} };
    e.ForEach(function (p) {
      roots['#'][p.mainDept] = '#';
      roots['mainDept'][p.dept] = p.mainDept;
      roots['dept'][p.SubDept] = p.dept;
      roots['SubDept'][p.name] = p.SubDept;
    });
    function makeNode(root) {
      return Enumerable.From(roots[root]).Select("{ parent: $.Value, id: $.Key, text: $.Key }");
    }
    return makeNode('#').Concat(makeNode('mainDept')).Concat(makeNode('dept')).Concat(makeNode('SubDept'));
  })
  .ToArray();

fiddle

0
On

First you have to parse your personArray into json acceptable by jsTree and then feed it to jsTree initialisation. I can't help you with linq, but with plain javascript it could work like in this demo - Fiddle.