11import { Component , computed , inject , input , output } from '@angular/core' ;
2+ import { VALUE_CLICK_HANDLERS } from '../handlers' ;
23import { ID_GENERATOR } from '../services/id-generator' ;
3- import { IsClickableValueFn , Segment } from '../types' ;
4+ import { IsClickableValueFn , Segment , ValueClickHandler } from '../types' ;
45import { decycle , previewString } from '../util' ;
56
67/**
@@ -40,16 +41,21 @@ export class NgxJsonTreeviewComponent {
4041 depth = input < number > ( - 1 ) ;
4142
4243 /**
43- * If `true`, value nodes will emit an `onValueClick` event when clicked. This
44- * allows for some interesting use cases, such as:
45- * - Rendering preformatted text, html, markdown, etc in another component.
44+ * If `true`, values are clickable when there is a corresponding handler
45+ * in the `valueClickHandlers` array that can process it.
46+ *
47+ * This allows for use cases such as:
48+ * - Following hyperlinks.
4649 * - Copying a value to the clipboard.
47- * - Following hyperlinks, etc
50+ * - Triggering custom actions based on the value's content or type.
4851 * @default false
4952 */
5053 enableClickableValues = input < boolean > ( false ) ;
5154
5255 /**
56+ * @deprecated Use `valueClickHandlers` instead. This input will be removed
57+ * in a future version.
58+ *
5359 * A function that determines if a specific value node should be considered
5460 * clickable. This provides more granular control than the global
5561 * `enableClickableValues` flag.
@@ -61,18 +67,29 @@ export class NgxJsonTreeviewComponent {
6167 * @param segment - The segment being evaluated.
6268 * @returns `true` if the segment's value should be clickable, `false`
6369 * otherwise.
64- * @default () => true - By default, all values are considered clickable if
65- * `enableClickableValues` is true.
6670 */
67- isClickableValue = input < IsClickableValueFn > ( ( ) => true ) ;
71+ isClickableValue = input < IsClickableValueFn > ( ) ;
6872
6973 /**
74+ * @deprecated Use `valueClickHandlers` instead. This output will be removed
75+ * in a future version.
76+ *
7077 * If `enableClickableValues` is set to `true`, emits a `Segment` object when
7178 * a value node is clicked. The emitted `Segment` contains details about the
7279 * clicked node (key, value, type, path, etc.).
7380 */
7481 onValueClick = output < Segment > ( ) ;
7582
83+ /**
84+ * An array of handler functions to be executed when a value node is clicked.
85+ * Only the first handler in the array for which `isClickable` returns `true`
86+ * will be executed.
87+ *
88+ * If `enableClickableValues` is set to true, but `valueClickHandlers` is
89+ * omitted, the built-in `VALUE_CLICK_HANDLERS` will be used as the default.
90+ */
91+ valueClickHandlers = input < ValueClickHandler [ ] > ( ) ;
92+
7693 /**
7794 * *Internal* input representing the parent segment in the tree hierarchy.
7895 * Primrily used for calculating paths.
@@ -87,6 +104,21 @@ export class NgxJsonTreeviewComponent {
87104 */
88105 _currentDepth = input < number > ( 0 ) ;
89106
107+ private internalValueClickHandlers = computed < ValueClickHandler [ ] > ( ( ) => {
108+ const handlers : ValueClickHandler [ ] = [ ] ;
109+ const legacyIsClickableFn = this . isClickableValue ( ) ;
110+
111+ if ( legacyIsClickableFn ) {
112+ handlers . push ( {
113+ canHandle : legacyIsClickableFn ,
114+ handler : ( segment ) => this . onValueClick . emit ( segment ) ,
115+ } ) ;
116+ }
117+
118+ handlers . push ( ...( this . valueClickHandlers ( ) ?? VALUE_CLICK_HANDLERS ) ) ;
119+ return handlers ;
120+ } ) ;
121+
90122 rootType = computed < string > ( ( ) => {
91123 if ( this . json ( ) === null ) {
92124 return 'null' ;
@@ -160,8 +192,18 @@ export class NgxJsonTreeviewComponent {
160192 ) ;
161193 }
162194
163- isClickable ( segment : Segment ) {
164- return this . enableClickableValues ( ) && this . isClickableValue ( ) ( segment ) ;
195+ isClickable ( segment : Segment ) : boolean {
196+ if ( ! this . enableClickableValues ( ) ) {
197+ return false ;
198+ }
199+
200+ return this . internalValueClickHandlers ( ) . some ( ( handler ) => {
201+ try {
202+ return handler . canHandle ( segment ) ;
203+ } catch ( e ) {
204+ return false ;
205+ }
206+ } ) ;
165207 }
166208
167209 toggle ( segment : Segment ) {
@@ -178,8 +220,19 @@ export class NgxJsonTreeviewComponent {
178220 }
179221
180222 onValueClickHandler ( segment : Segment ) {
181- if ( this . isClickable ( segment ) ) {
182- this . onValueClick . emit ( segment ) ;
223+ for ( const handler of this . internalValueClickHandlers ( ) ) {
224+ try {
225+ if ( handler . canHandle ( segment ) ) {
226+ try {
227+ handler . handler ( segment ) ;
228+ } catch ( e ) {
229+ console . error ( 'Error executing click handler:' , e ) ;
230+ }
231+ return ; // Stop after the first handler is executed.
232+ }
233+ } catch ( e ) {
234+ // in case of any error, continue to the next handler
235+ }
183236 }
184237 }
185238
0 commit comments