@@ -216,6 +216,27 @@ describe('MatTree', () => {
216
216
} ) ;
217
217
} ) ;
218
218
219
+ describe ( 'flat tree with undefined or null children' , ( ) => {
220
+ describe ( 'should initialize' , ( ) => {
221
+ let fixture : ComponentFixture < MatTreeWithNullOrUndefinedChild > ;
222
+
223
+ beforeEach ( ( ) => {
224
+ configureMatTreeTestingModule ( [ MatTreeWithNullOrUndefinedChild ] ) ;
225
+ fixture = TestBed . createComponent ( MatTreeWithNullOrUndefinedChild ) ;
226
+ treeElement = fixture . nativeElement . querySelector ( 'mat-tree' ) ;
227
+
228
+ fixture . detectChanges ( ) ;
229
+ } ) ;
230
+
231
+ it ( 'with rendered dataNodes' , ( ) => {
232
+ const nodes = getNodes ( treeElement ) ;
233
+
234
+ expect ( nodes ) . toBeDefined ( 'Expect nodes to be defined' ) ;
235
+ expect ( nodes [ 0 ] . classList ) . toContain ( 'customNodeClass' ) ;
236
+ } ) ;
237
+ } ) ;
238
+ } ) ;
239
+
219
240
describe ( 'nested tree' , ( ) => {
220
241
describe ( 'should initialize' , ( ) => {
221
242
let fixture : ComponentFixture < NestedMatTreeApp > ;
@@ -610,6 +631,85 @@ class SimpleMatTreeApp {
610
631
}
611
632
}
612
633
634
+ interface FoodNode {
635
+ name : string ;
636
+ children ?: FoodNode [ ] | null ;
637
+ }
638
+
639
+ /** Flat node with expandable and level information */
640
+ interface ExampleFlatNode {
641
+ expandable : boolean ;
642
+ name : string ;
643
+ level : number ;
644
+ }
645
+
646
+ /**
647
+ * Food data with nested structure.
648
+ * Each node has a name and an optiona list of children.
649
+ */
650
+ const TREE_DATA : FoodNode [ ] = [
651
+ {
652
+ name : 'Fruit' ,
653
+ children : [
654
+ { name : 'Apple' } ,
655
+ { name : 'Banana' } ,
656
+ { name : 'Fruit loops' ,
657
+ children : null } ,
658
+ ]
659
+ } , {
660
+ name : 'Vegetables' ,
661
+ children : [
662
+ {
663
+ name : 'Green' ,
664
+ children : [
665
+ { name : 'Broccoli' } ,
666
+ { name : 'Brussel sprouts' } ,
667
+ ]
668
+ } , {
669
+ name : 'Orange' ,
670
+ children : [
671
+ { name : 'Pumpkins' } ,
672
+ { name : 'Carrots' } ,
673
+ ]
674
+ } ,
675
+ ]
676
+ } ,
677
+ ] ;
678
+
679
+ @Component ( {
680
+ template : `
681
+ <mat-tree [dataSource]="dataSource" [treeControl]="treeControl">
682
+ <mat-tree-node *matTreeNodeDef="let node" class="customNodeClass"
683
+ matTreeNodePadding matTreeNodeToggle>
684
+ {{node.name}}
685
+ </mat-tree-node>
686
+ </mat-tree>
687
+ `
688
+ } )
689
+ class MatTreeWithNullOrUndefinedChild {
690
+ private transformer = ( node : FoodNode , level : number ) => {
691
+ return {
692
+ expandable : ! ! node . children ,
693
+ name : node . name ,
694
+ level : level ,
695
+ } ;
696
+ }
697
+
698
+ treeControl = new FlatTreeControl < ExampleFlatNode > (
699
+ node => node . level , node => node . expandable ) ;
700
+
701
+ treeFlattener = new MatTreeFlattener (
702
+ this . transformer , node => node . level , node => node . expandable , node => node . children ) ;
703
+
704
+ dataSource = new MatTreeFlatDataSource ( this . treeControl , this . treeFlattener , TREE_DATA ) ;
705
+
706
+ constructor ( ) {
707
+ this . dataSource . data = TREE_DATA ;
708
+ }
709
+
710
+ hasChild = ( _ : number , node : ExampleFlatNode ) => node . expandable ;
711
+ }
712
+
613
713
@Component ( {
614
714
template : `
615
715
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl">
0 commit comments