Skip to content

Commit 2c300ec

Browse files
authored
Merge pull request #257 from harunurhan/menu-max-depth
add menuMaxDepth config
2 parents 67436d8 + 348582b commit 2c300ec

File tree

8 files changed

+173
-8
lines changed

8 files changed

+173
-8
lines changed

example/app/app.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export class AppConfig {
5959
}
6060
},
6161
enableAdminModeSwitch: true,
62+
menuMaxDepth: 1,
6263
tabsConfig: {
6364
defaultTabName: 'Main',
6465
tabs: [

src/json-editor.component.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@ export class JsonEditorComponent extends AbstractTrackerComponent implements OnI
142142
this.activeTabName = tabName;
143143
});
144144
this.appGlobalsService.activeTabName = this.config.tabsConfig.defaultTabName;
145+
146+
// set config to make it globally accessible all over the app
147+
this.appGlobalsService.config = this.config;
145148
}
146149

147150
}

src/shared/interfaces/json-editor-config.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ export interface JsonEditorConfig {
1111
*/
1212
enableAdminModeSwitch?: boolean;
1313

14+
/**
15+
* Max depth for tree menu
16+
*
17+
* - It is `infinity` by default
18+
* - Must be set to 1 or greater.
19+
*/
20+
menuMaxDepth?: number;
21+
1422
/**
1523
* Configurations for properties defined in the schema.
1624
*

src/shared/services/app-globals.service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
import { Injectable, TemplateRef } from '@angular/core';
2424
import { ReplaySubject } from 'rxjs/ReplaySubject';
25-
import { SchemaValidationErrors } from '../interfaces';
25+
import { SchemaValidationErrors, JsonEditorConfig } from '../interfaces';
2626

2727
@Injectable()
2828
export class AppGlobalsService {
@@ -31,6 +31,7 @@ export class AppGlobalsService {
3131
public activeTabName = '';
3232
public tabNameToFirstTopLevelElement: { [tabName: string]: string } = {};
3333
public templates: { [templateName: string]: TemplateRef<any> };
34+
public config: JsonEditorConfig;
3435

3536
set globalErrors(errors: SchemaValidationErrors) {
3637
this._globalErrorsSubject.next(errors);

src/tree-menu/tree-menu-item.component.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
<div>
22
<a [href]="href" (click)="toggle($event)">{{label}}</a>
33
<a *ngIf="isCollapsable" [hidden]="isCollapsed" (click)="collapse()"> [x]</a>
4-
<div [ngSwitch]="schema.type" [hidden]="isCollapsed">
4+
<div *ngIf="isNotLeaf" [ngSwitch]="schema.type" [hidden]="isCollapsed">
55
<ul>
66
<div *ngSwitchCase="'object'">
77
<li *ngFor="let key of keys | addAlwaysShowFields:schema | filterAndSortBySchema:schema; trackBy:trackByElement">
8-
<tree-menu-item [label]="key" [value]="value.get(key)" [schema]="schema.properties[key]" [path]="getChildPath(key)"></tree-menu-item>
8+
<tree-menu-item [label]="key" [value]="value.get(key)" [schema]="schema.properties[key]" [path]="getChildPath(key)" [depth]="depth + 1"></tree-menu-item>
99
</li>
1010
</div>
1111
<div *ngSwitchCase="'array'">
1212
<li *ngFor="let element of value; let i = index; trackBy:trackByElement">
13-
<tree-menu-item [label]="i" [value]="element" [schema]="schema.items" [path]="getChildPath(i)"></tree-menu-item>
13+
<tree-menu-item [label]="i" [value]="element" [schema]="schema.items" [path]="getChildPath(i)" [depth]="depth + 1"></tree-menu-item>
1414
</li>
1515
</div>
1616
</ul>

src/tree-menu/tree-menu-item.component.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { AbstractTrackerComponent } from '../abstract-tracker';
2626

2727
import { Map, Set } from 'immutable';
2828

29-
import { DomUtilService, WindowHrefService, PathUtilService } from '../shared/services';
29+
import { DomUtilService, WindowHrefService, PathUtilService, AppGlobalsService } from '../shared/services';
3030
import { JSONSchema } from '../shared/interfaces';
3131

3232
@Component({
@@ -43,6 +43,7 @@ export class TreeMenuItemComponent extends AbstractTrackerComponent implements O
4343
@Input() value: any;
4444
@Input() schema: JSONSchema;
4545
@Input() path: string;
46+
@Input() depth: number;
4647

4748
// defined only if schmea.type equals to 'object'
4849
keys: Set<string>;
@@ -52,7 +53,8 @@ export class TreeMenuItemComponent extends AbstractTrackerComponent implements O
5253

5354
constructor(private windowHrefService: WindowHrefService,
5455
private domUtilService: DomUtilService,
55-
private pathUtilService: PathUtilService) {
56+
private pathUtilService: PathUtilService,
57+
private appGlobalsService: AppGlobalsService) {
5658
super();
5759
}
5860

@@ -83,7 +85,15 @@ export class TreeMenuItemComponent extends AbstractTrackerComponent implements O
8385

8486
get isCollapsable(): boolean {
8587
let schemaType = this.schema.type;
86-
return (schemaType === 'object' || schemaType === 'array');
88+
return this.isNotLeaf && (schemaType === 'object' || schemaType === 'array');
89+
}
90+
91+
get maxDepth(): number {
92+
return this.appGlobalsService.config.menuMaxDepth;
93+
}
94+
95+
get isNotLeaf(): boolean {
96+
return this.maxDepth === undefined || this.depth < this.maxDepth;
8797
}
8898

8999
getChildPath(indexOrKey: number | string) {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<div class="tree-menu-container">
22
<ul class="menu-item-container">
33
<li *ngFor="let key of keys | addAlwaysShowFields:schema | filterAndSortBySchema:schema; trackBy:trackByElement">
4-
<tree-menu-item [label]="key" [value]="record.get(key)" [schema]="schema.properties[key]" [path]="getChildPath(key)"></tree-menu-item>
4+
<tree-menu-item [label]="key" [value]="record.get(key)" [schema]="schema.properties[key]" [path]="getChildPath(key)" [depth]="1"></tree-menu-item>
55
</li>
66
</ul>
77
</div>
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*
2+
* This file is part of ng2-json-editor.
3+
* Copyright (C) 2016 CERN.
4+
*
5+
* ng2-json-editor is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU General Public License as
7+
* published by the Free Software Foundation; either version 2 of the
8+
* License, or (at your option) any later version.
9+
*
10+
* ng2-json-editor is distributed in the hope that it will be useful, but
11+
* WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with ng2-json-editor; if not, write to the Free Software Foundation, Inc.,
17+
* 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
18+
* In applying this license, CERN does not
19+
* waive the privileges and immunities granted to it by virtue of its status
20+
* as an Intergovernmental Organization or submit itself to any jurisdiction.
21+
*/
22+
23+
import {
24+
async,
25+
ComponentFixture,
26+
TestBed
27+
} from '@angular/core/testing';
28+
29+
import { Component } from '@angular/core';
30+
31+
import { fromJS, Map } from 'immutable';
32+
33+
import { TreeMenuItemComponent } from './tree-menu-item.component';
34+
import { TreeMenuComponent } from './tree-menu.component';
35+
36+
import {
37+
DomUtilService,
38+
PathUtilService,
39+
WindowHrefService,
40+
AppGlobalsService,
41+
TabsUtilService
42+
} from '../shared/services';
43+
44+
import {
45+
AddAlwaysShowFieldsPipe,
46+
FilterAndSortBySchemaPipe
47+
} from '../shared/pipes';
48+
49+
50+
/**
51+
* Wrap tree-menu in a host component to be able trigger `ngOnChanges`
52+
*/
53+
@Component({
54+
template: '<tree-menu [record]="record" [schema]="schema"></tree-menu>'
55+
})
56+
class TestHostComponent {
57+
schema = {
58+
type: 'object',
59+
properties: {
60+
anArray: {
61+
type: 'array',
62+
items: {
63+
type: 'object',
64+
properties: {
65+
aString: {
66+
type: 'string'
67+
}
68+
}
69+
}
70+
}
71+
}
72+
};
73+
74+
record: Map<string, any> = fromJS({
75+
anArray: [
76+
{
77+
aString: 'foo'
78+
},
79+
{
80+
aString: 'bar'
81+
}
82+
]
83+
});
84+
firstLevelKeysCount = 1;
85+
allKeysCount = 5;
86+
}
87+
88+
describe('TreeMenuComponent', () => {
89+
90+
let fixture: ComponentFixture<TestHostComponent>;
91+
let component: TestHostComponent;
92+
let nativeEl: HTMLElement;
93+
let appGlobalsService = new AppGlobalsService();
94+
95+
beforeEach(async(() => {
96+
TestBed.configureTestingModule({
97+
declarations: [
98+
TestHostComponent,
99+
TreeMenuComponent,
100+
TreeMenuItemComponent,
101+
AddAlwaysShowFieldsPipe,
102+
FilterAndSortBySchemaPipe
103+
],
104+
imports: [
105+
106+
],
107+
providers: [
108+
PathUtilService,
109+
WindowHrefService,
110+
DomUtilService,
111+
TabsUtilService,
112+
{ provide: AppGlobalsService, useValue: appGlobalsService }
113+
]
114+
}).compileComponents();
115+
}));
116+
117+
beforeEach(() => {
118+
fixture = TestBed.createComponent(TestHostComponent);
119+
component = fixture.componentInstance;
120+
appGlobalsService.config = {};
121+
fixture.detectChanges();
122+
nativeEl = fixture.nativeElement;
123+
});
124+
125+
it('should be nested if menuMaxDepth is not set', () => {
126+
let menuItemsCount = nativeEl.querySelectorAll('tree-menu-item').length;
127+
128+
expect(menuItemsCount).toEqual(component.allKeysCount);
129+
});
130+
131+
it('should not go deeper than menuMaxDepth', () => {
132+
appGlobalsService.config = { menuMaxDepth: 1 };
133+
// Create the component again to render with new menuMaxDepth
134+
fixture = TestBed.createComponent(TestHostComponent);
135+
component = fixture.componentInstance;
136+
nativeEl = fixture.nativeElement;
137+
fixture.detectChanges();
138+
139+
let menuItemsCount = nativeEl.querySelectorAll('tree-menu-item').length;
140+
expect(menuItemsCount).toEqual(component.firstLevelKeysCount);
141+
});
142+
});

0 commit comments

Comments
 (0)