diff --git a/README.md b/README.md index 3c99a1b..dd7f2fc 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ngx-json-treeview -A collapsible JSON tree view for Angular +A simple Angular component to display JSON data in an expandable tree view. image @@ -10,12 +10,39 @@ A collapsible JSON tree view for Angular npm install ngx-json-treeview ``` +## Key Features + +- Expandable/collapsible nodes. +- Configurable initial expansion state and depth. +- Optional click handling for value nodes. + ## Usage +To render JSON in its fully expanded state. + ```html ``` +To render JSON with all nodes collapsed. + +```html + +``` + +Alternatively, expand only to a max depth by default. + +```html + +``` + +You can enable the user to click on values. Provide `onValueClick` to implement +the desired behavior. + +```html + +``` + ## Demo [https://stackblitz.com/edit/ngx-json-treeview](https://stackblitz.com/edit/ngx-json-treeview?file=src%2Fapp%2Fapp.component.ts) diff --git a/projects/demo/src/app/app.component.html b/projects/demo/src/app/app.component.html index 6857181..eeb4bed 100644 --- a/projects/demo/src/app/app.component.html +++ b/projects/demo/src/app/app.component.html @@ -14,3 +14,21 @@

Fully Expanded

+ +

Clickable Nodes

+
+
+ +
+ + @let segment = currentSegment(); + @if (segment) { +
+
{{ stringify(segment.value) }}
+
+ } +
diff --git a/projects/demo/src/app/app.component.scss b/projects/demo/src/app/app.component.scss index b92cf0f..14bc1fe 100644 --- a/projects/demo/src/app/app.component.scss +++ b/projects/demo/src/app/app.component.scss @@ -1,3 +1,22 @@ .json-container { font-family: monospace; + overflow: hidden; + padding: 10px; +} + +.clickable-container { + display: flex; + gap: 10px; + width: 100%; +} + +.clickable-container > .json-container, +.clickable-container > .preview-pane { + box-sizing: border-box; + flex-basis: 50%; +} + +.preview-pane { + border-left: 1px solid #ccc; + padding: 10px; } diff --git a/projects/demo/src/app/app.component.ts b/projects/demo/src/app/app.component.ts index cad1a54..7ccd0cd 100644 --- a/projects/demo/src/app/app.component.ts +++ b/projects/demo/src/app/app.component.ts @@ -1,5 +1,5 @@ -import { Component } from '@angular/core'; -import { NgxJsonTreeviewComponent } from 'ngx-json-treeview'; +import { Component, signal } from '@angular/core'; +import { NgxJsonTreeviewComponent, Segment } from 'ngx-json-treeview'; @Component({ selector: 'app-root', @@ -8,6 +8,8 @@ import { NgxJsonTreeviewComponent } from 'ngx-json-treeview'; styleUrl: './app.component.scss', }) export class AppComponent { + currentSegment = signal(undefined); + baseObj = { string: 'Hello World', number: 1234567890, @@ -39,4 +41,12 @@ export class AppComponent { return 'baz'; }, }; + + onValueClick(segment: Segment) { + this.currentSegment.set(segment); + } + + stringify(obj: any) { + return typeof obj === 'function' ? '' + obj : JSON.stringify(obj, null, 2); + } } diff --git a/projects/ngx-json-treeview/src/lib/ngx-json-treeview.component.html b/projects/ngx-json-treeview/src/lib/ngx-json-treeview.component.html index 6631ad2..bd9497b 100644 --- a/projects/ngx-json-treeview/src/lib/ngx-json-treeview.component.html +++ b/projects/ngx-json-treeview/src/lib/ngx-json-treeview.component.html @@ -5,22 +5,24 @@ @for (segment of segments(); track segment) {
@let expandable = isExpandable(segment); -
- @if (expandable) { -
- } - {{ segment.key }} +
+ + @if (expandable) { +
+ } + {{ segment.key }} +
: @if (!expandable || !segment.expanded) { - {{ - segment.description - }} + + {{ segment.description }} + } @else if (expandable && segment.expanded) { @if (segment.type === 'array') { @@ -37,7 +39,10 @@ [json]="segment.value" [expanded]="expanded()" [depth]="depth()" - [_currentDepth]="_currentDepth() + 1" /> + [enableClickableValues]="enableClickableValues()" + [_parent]="segment" + [_currentDepth]="_currentDepth() + 1" + (onValueClick)="onValueClickHandler($event)" /> @if (['object', 'array'].includes(segment.type ?? '')) { @if (segment.type === 'array') { diff --git a/projects/ngx-json-treeview/src/lib/ngx-json-treeview.component.scss b/projects/ngx-json-treeview/src/lib/ngx-json-treeview.component.scss index 08b3ef7..abc360a 100644 --- a/projects/ngx-json-treeview/src/lib/ngx-json-treeview.component.scss +++ b/projects/ngx-json-treeview/src/lib/ngx-json-treeview.component.scss @@ -93,6 +93,15 @@ $type-colors: ( cursor: pointer; } + .clickable { + cursor: pointer; + text-decoration: none; + + &:hover { + text-decoration: underline; + } + } + .puctuation { color: var(--ngx-json-punctuation, #000); } diff --git a/projects/ngx-json-treeview/src/lib/ngx-json-treeview.component.ts b/projects/ngx-json-treeview/src/lib/ngx-json-treeview.component.ts index d6bcb4b..3d5590b 100644 --- a/projects/ngx-json-treeview/src/lib/ngx-json-treeview.component.ts +++ b/projects/ngx-json-treeview/src/lib/ngx-json-treeview.component.ts @@ -1,13 +1,15 @@ import { CommonModule } from '@angular/common'; -import { Component, computed, input } from '@angular/core'; +import { Component, computed, input, output } from '@angular/core'; import { decycle, previewString } from './util'; export interface Segment { key: string; value: any; - type: undefined | string; + type?: string; description: string; expanded: boolean; + parent?: Segment; + path: string; } @Component({ @@ -21,8 +23,13 @@ export class NgxJsonTreeviewComponent { json = input.required(); expanded = input(true); depth = input(-1); + enableClickableValues = input(false); + + _parent = input(); _currentDepth = input(0); + onValueClick = output(); + // computed values segments = computed(() => { const json = decycle(this.json()); @@ -55,8 +62,16 @@ export class NgxJsonTreeviewComponent { } } + onValueClickHandler(segment: Segment) { + if (this.enableClickableValues()) { + this.onValueClick.emit(segment); + } + } + private parseKeyValue(key: any, value: any): Segment { const segment: Segment = { + parent: this._parent(), + path: this._parent() ? `${this._parent()!.path}.${key}` : key, key: key, value: value, type: undefined,