带复选框的Angular Material Tree视图的JSON填充不正确

时间:2019-06-02 02:41:31

标签: json angular typescript treeview material

我正在尝试为一个项目创建带有复选框的材料树视图。我已经在stackover流程中寻找了类似的实现,但是不幸的是我没有获得任何成功。我希望这将成为其他尝试这样做的人的资源!

我当前正在阅读/实现的文档来自https://material.angular.io/components/tree/examples

我正在使用Angular 7ASP.NET Core 3.0

  

问题:

我能够用ASP.NET返回的JSON结果填充节点,但是不幸的是,数组位置以及ID和名称都被填充,这不是期望的结果。我要返回的是带有ID的名称。

即:0: {outterId: "101", name: "Groceries", innerArray1: [{…}, {…}]}1: {outterId: "201", name: "Groceries1", innerArray1: [{…}, {…}]}

例如,在Angular 7 Material documentation中,他们具有以下JSON结构:

const TREE_DATA = {
  Groceries: {
    'Almond Meal flour': null,
    'Organic eggs': null,
    'Protein Powder': null,
    Fruits: {
      Apple: null,
      Berries: ['Blueberry', 'Raspberry'],
      Orange: null
    }
  },
  Reminders: [
    'Cook dinner',
    'Read the Material Design spec',
    'Upgrade Application to Angular'
  ]
};

我从JSON返回的ASP.NET给了我一些嵌套的JSON

[
  {
    "outterId": 201,
    "outterName": "Groceries",
    "innerArray1": [
      {
        "innerArray1Id": 212,
        "innerName1": "Almond Meal Flour"
        "innerArray2": [
          {
            "innerArray2Id": 313,
            "innerName2": "Almond Meal bread",
          },
          {
            "innerArray2Id": 414,
            "innerName2": "Almond Milk",
          }
        ]
      },
      {
        "innerArray1Id": 11111,
        "innerName1": "Fruits",
        "innerArray2": [
          {
            "innerArray2Id": 1414,
            "innerName2": "Apple",
          },
          {
            "innerArray2Id": 9616,
            "innerName2": "Berries",
          }
        ]
      }
    ]
  }
]

[
  {
    "outterId": 211,
    "outterName": "Groceries2",
    "innerArray1": [
      {
        "innerArray1Id": 213,
        "innerName1": "Organic eggs"
        "innerArray2": [
          {
            "innerArray2Id": 314,
            "innerName2": "Egg nog",
          },
          {
            "innerArray2Id": 415,
            "innerName2": "Egg mixtures",
          }
        ]
      },
      {
        "innerArray1Id": 11112,
        "innerName1": "Fruits",
        "innerArray2": [
          {
            "innerArray2Id": 1415,
            "innerName2": "Orange",
          },
          {
            "innerArray2Id": 9617,
            "innerName2": "Raspberry",
          }
        ]
      }
    ]
  }
]

我得到的是这样的:

0 +
  201
  Groceries
  innerArray1 +
   201 +
       212
       Almond Meal Flour
       innerArray2 +
       313
       Almond Meal bread
       414
       Almond Milk
       .
       .
       etc.
1 +
  212
  Groceries2
  innerArray1 +
   213 +
       Organic eggs
       innerArray2 +
       314
       Egg nog
       415
       Egg mixtures
       .
       .
       etc.  

我想要的是:

Groceries +
             Almond Meal Flour +
                    Almond Meal Bread
                    Almond Milk

             Fruits +
                Apple
                Berries
                .
                .
                etc.
  

GroceryService

groceryList() {
 return this.http.get(this.url + 'produce/groceries');
}
  

ts文件


export class TodoItemNode {
  innerArray1: TodoItemNode[];
  innerArray2: TodoItemNode[];
  outterName: string;
  outterId: number;
  innerArray1Id: number;
  innerName1: string;
  innerArray2Id: number;
  innerName2: string;
}

export class TodoItemFlatNode {
  item: string;
  level: number;
  expandable: boolean;
}


@Component({
  selector: 'tsFiletest',
  templateUrl: './tsFiletest.component.html',
  styleUrls: ['./tsFiletest.component.css'],
})

export class TSFileTest implements OnInit{

  dataChange = new BehaviorSubject<TodoItemNode[]>([]);

  get data(): TodoItemNode[] { return this.dataChange.value; }


  //This is where the actual building of the tree begins.

  buildFileTree(obj: {[key: string]: any}, level: number): TodoItemNode[] {
    return Object.keys(obj).reduce<TodoItemNode[]>((accumulator, key) => {
      const value = obj[key];

      const node = new TodoItemNode();
      node.outterName = key;  //The array position i.e. 0 and 1 is actually assigned here.

      if (value != null) {
        if (typeof value === 'object') {

          node.innerArray1 = this.buildFileTree(value, level + 1);
          //node.innerArray2 = this.buildFileTree(value, level + 1); //I'm not sure if I should be building the inner array2 here.

        } else {
          node.outterName = value;
        }
      }

      return accumulator.concat(node);
    }, []);
  }

  insertItem(parent: TodoItemNode, name: string) {
    if (parent.innerArray1) {
      parent.innerArray1.push({outterName: name} as TodoItemNode);
      this.dataChange.next(this.data);
    }
  }

  updateItem(node: TodoItemNode, name: string) {
    node.outterName = name;
    this.dataChange.next(this.data);
  }

   flatNodeMap = new Map<TodoItemFlatNode, TodoItemNode>();

   nestedNodeMap = new Map<TodoItemNode, TodoItemFlatNode>();

   selectedParent: TodoItemFlatNode | null = null;

   newItemName = '';

   treeControl: FlatTreeControl<TodoItemFlatNode>;

   treeFlattener: MatTreeFlattener<TodoItemNode, TodoItemFlatNode>;

   dataSource: MatTreeFlatDataSource<TodoItemNode, TodoItemFlatNode>;

   checklistSelection = new SelectionModel<TodoItemFlatNode>(true /* multiple */);

   constructor(private _database: ChecklistDatabase, private groceryService: GroceryService) {
     this.treeFlattener = new MatTreeFlattener(this.transformer, this.getLevel,
       this.isExpandable, this.getChildren);
     this.treeControl = new FlatTreeControl<TodoItemFlatNode>(this.getLevel, this.isExpandable);
     this.dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);

     this.getGroceryList(); //initialize

     this.dataChange.subscribe(data => {
       this.dataSource.data = data;
     });
   }


   groceryListResponse: any = [];
   groceryList: TodoItemNode[];

   ngOnInit() {
      this.getGroceryList();
   }

   getGroceryList() {
     return this.groceryService.groceryList().subscribe(res => {
       this.groceryListResponse = res;
       this.groceryList = this.groceryListResponse;

       const data = this.buildFileTree(this.groceryList, 0);

       // Notify the change.
       this.dataChange.next(data); 
     });
   }

   getLevel = (node: TodoItemFlatNode) => node.level;

   isExpandable = (node: TodoItemFlatNode) => node.expandable;

   getChildren = (node: TodoItemNode): TodoItemNode[] => node.innerArray1;

   hasChild = (_: number, _nodeData: TodoItemFlatNode) => _nodeData.expandable;

   hasNoContent = (_: number, _nodeData: TodoItemFlatNode) => _nodeData.item === '';

   transformer = (node: TodoItemNode, level: number) => {
     const existingNode = this.nestedNodeMap.get(node);
     const flatNode = existingNode && existingNode.item === node.outterName
         ? existingNode
         : new TodoItemFlatNode();
     flatNode.item = node.outterName;
     flatNode.level = level;
     flatNode.expandable = !!node.innerArray1;
     this.flatNodeMap.set(flatNode, node);
     this.nestedNodeMap.set(node, flatNode);
     return flatNode;
   }

   descendantsAllSelected(node: TodoItemFlatNode): boolean {
     const descendants = this.treeControl.getDescendants(node);
     const descAllSelected = descendants.every(child =>
       this.checklistSelection.isSelected(child)
     );
     return descAllSelected;
   }

   descendantsPartiallySelected(node: TodoItemFlatNode): boolean {
     const descendants = this.treeControl.getDescendants(node);
     const result = descendants.some(child => this.checklistSelection.isSelected(child));
     return result && !this.descendantsAllSelected(node);
   }

   todoItemSelectionToggle(node: TodoItemFlatNode): void {
     this.checklistSelection.toggle(node);
     const descendants = this.treeControl.getDescendants(node);
     this.checklistSelection.isSelected(node)
       ? this.checklistSelection.select(...descendants)
       : this.checklistSelection.deselect(...descendants);

     // Force update for the parent
     descendants.every(child =>
       this.checklistSelection.isSelected(child)
     );
     this.checkAllParentsSelection(node);
   }

   /** Toggle a leaf to-do item selection. Check all the parents to see if they changed */
   todoLeafItemSelectionToggle(node: TodoItemFlatNode): void {
     this.checklistSelection.toggle(node);
     this.checkAllParentsSelection(node);
   }

   /* Checks all the parents when a leaf node is selected/unselected */
   checkAllParentsSelection(node: TodoItemFlatNode): void {
     let parent: TodoItemFlatNode | null = this.getParentNode(node);
     while (parent) {
       this.checkRootNodeSelection(parent);
       parent = this.getParentNode(parent);
     }
   }

   /** Check root node checked state and change it accordingly */
   checkRootNodeSelection(node: TodoItemFlatNode): void {
     const nodeSelected = this.checklistSelection.isSelected(node);
     const descendants = this.treeControl.getDescendants(node);
     const descAllSelected = descendants.every(child =>
       this.checklistSelection.isSelected(child)
     );
     if (nodeSelected && !descAllSelected) {
       this.checklistSelection.deselect(node);
     } else if (!nodeSelected && descAllSelected) {
       this.checklistSelection.select(node);
     }
   }

   /* Get the parent node of a node */
   getParentNode(node: TodoItemFlatNode): TodoItemFlatNode | null {
     const currentLevel = this.getLevel(node);

     if (currentLevel < 1) {
       return null;
     }

     const startIndex = this.treeControl.dataNodes.indexOf(node) - 1;

     for (let i = startIndex; i >= 0; i--) {
       const currentNode = this.treeControl.dataNodes[i];

       if (this.getLevel(currentNode) < currentLevel) {
         return currentNode;
       }
     }
     return null;
   }

   /** Select the category so we can insert the new item. */
   addNewItem(node: TodoItemFlatNode) {
     const parentNode = this.flatNodeMap.get(node);
     this.insertItem(parentNode!, '');
     this.treeControl.expand(node);
   }

   /** Save the node to database */
   saveNode(node: TodoItemFlatNode, itemValue: string) {
     const nestedNode = this.flatNodeMap.get(node);
     this.updateItem(nestedNode!, itemValue);
   }
}



0 个答案:

没有答案