diff --git a/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.test.tsx b/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.test.tsx
index 0b54c3ef717..3974ab7cb52 100644
--- a/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.test.tsx
+++ b/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.test.tsx
@@ -14,6 +14,7 @@ describe('PillCell', () => {
type: FieldType.string,
values: values,
config: {},
+ display: (value: unknown) => ({ text: String(value), color: '#FF780A', numeric: NaN }),
});
const ser = new XMLSerializer();
@@ -119,6 +120,29 @@ describe('PillCell', () => {
`
);
});
+
+ it('custom display text', () => {
+ const mockField = fieldWithValues(['value1,value2,value3']);
+ const field = {
+ ...mockField,
+ display: (value: unknown) => ({
+ text: `${value} lbs`,
+ color: '#FF780A',
+ numeric: 0,
+ }),
+ } satisfies Field;
+
+ expectHTML(
+ render(
+
+ ),
+ `
+ value1 lbs
+ value2 lbs
+ value3 lbs
+ `
+ );
+ });
});
describe('Color by value mappings', () => {
diff --git a/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.tsx b/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.tsx
index baf3715eb77..92c7aff6f9a 100644
--- a/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.tsx
+++ b/packages/grafana-ui/src/components/Table/TableNG/Cells/PillCell.tsx
@@ -8,6 +8,7 @@ import {
getColorByStringHash,
FALLBACK_COLOR,
fieldColorModeRegistry,
+ formattedValueToString,
} from '@grafana/data';
import { FieldColorModeId } from '@grafana/schema';
@@ -20,10 +21,11 @@ export function PillCell({ rowIdx, field, theme, getTextColorForBackground }: Pi
const pillValues = inferPills(value);
return pillValues.length > 0
? pillValues.map((pill, index) => {
- const bgColor = getPillColor(pill, field, theme);
+ const renderedValue = formattedValueToString(field.display!(pill));
+ const bgColor = getPillColor(renderedValue, field, theme);
const textColor = getTextColorForBackground(bgColor);
return {
- value: String(pill),
+ value: renderedValue,
key: `${pill}-${index}`,
bgColor,
color: textColor,
diff --git a/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx b/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx
index 908642d94a0..06da0b2f5c9 100644
--- a/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx
+++ b/packages/grafana-ui/src/components/Table/TableNG/TableNG.tsx
@@ -438,7 +438,7 @@ export function TableNG(props: TableNGProps) {
// attach JSONCell custom display function to JSONView cell type
if (cellType === TableCellDisplayMode.JSONView || field.type === FieldType.other) {
- field.display = displayJsonValue;
+ field.display = displayJsonValue(field);
}
// For some cells, "aligning" the cell will mean aligning the inline contents of the cell with
diff --git a/packages/grafana-ui/src/components/Table/TableNG/utils.test.ts b/packages/grafana-ui/src/components/Table/TableNG/utils.test.ts
index 946ee3fd799..ef295d72652 100644
--- a/packages/grafana-ui/src/components/Table/TableNG/utils.test.ts
+++ b/packages/grafana-ui/src/components/Table/TableNG/utils.test.ts
@@ -47,6 +47,7 @@ import {
getDisplayName,
predicateByName,
calculateFooterHeight,
+ displayJsonValue,
} from './utils';
describe('TableNG utils', () => {
@@ -1354,10 +1355,35 @@ describe('TableNG utils', () => {
});
describe('displayJsonValue', () => {
- it.todo('should parse and then stringify string values');
- it.todo('should not throw for non-serializable string values');
- it.todo('should stringify non-string values');
- it.todo('should not throw for non-serializable non-string values');
+ let field: Field;
+ beforeEach(() => {
+ field = {
+ name: 'test',
+ type: FieldType.string,
+ config: {},
+ state: { displayName: 'Test Display Name' },
+ values: [],
+ display: (val: unknown) => ({ text: String(val), numeric: NaN }),
+ };
+ });
+
+ it('should parse and then stringify string values', () => {
+ expect(displayJsonValue(field)('{"valid": "json"}').text).toBe('{\n "valid": "json"\n}');
+ });
+
+ it('should not throw for non-serializable string values', () => {
+ expect(displayJsonValue(field)('{"invalid": "json').text).toBe('{"invalid": "json');
+ });
+
+ it('should stringify non-string values', () => {
+ expect(displayJsonValue(field)(42).text).toBe('42');
+ });
+
+ it('should use the underlying field.display method to format values and return numeric values', () => {
+ field.display = (val: unknown) => ({ text: `**${val}**`, numeric: Number(val), suffix: 'ms' });
+ expect(displayJsonValue(field)(42).text).toBe('**42**ms');
+ expect(displayJsonValue(field)(42).numeric).toBe(42);
+ });
});
describe('applySort', () => {
diff --git a/packages/grafana-ui/src/components/Table/TableNG/utils.ts b/packages/grafana-ui/src/components/Table/TableNG/utils.ts
index 22dcdf6a43f..c754a27200f 100644
--- a/packages/grafana-ui/src/components/Table/TableNG/utils.ts
+++ b/packages/grafana-ui/src/components/Table/TableNG/utils.ts
@@ -15,6 +15,7 @@ import {
DisplayValueAlignmentFactors,
DataFrame,
DisplayProcessor,
+ DecimalCount,
} from '@grafana/data';
import {
BarGaugeDisplayMode,
@@ -970,28 +971,24 @@ export function canFieldBeColorized(
);
}
-export const displayJsonValue: DisplayProcessor = (value: unknown): DisplayValue => {
- let displayValue: string;
+export const displayJsonValue: (field: Field) => DisplayProcessor = (field: Field, decimals?: DecimalCount) => {
+ const origDisplay = field.display!;
+ return (value: unknown): DisplayValue => {
+ let jsonText: string;
- // Handle string values that might be JSON
- if (typeof value === 'string') {
+ const displayValue = origDisplay(value, decimals);
+ const formattedValue = formattedValueToString(displayValue);
+
+ // Handle string values that might be JSON
try {
- const parsed = JSON.parse(value);
- displayValue = JSON.stringify(parsed, null, ' ');
+ const parsed = JSON.parse(formattedValue);
+ jsonText = JSON.stringify(parsed, null, ' ');
} catch {
- displayValue = value; // Keep original if not valid JSON
+ jsonText = formattedValue; // Keep original if not valid JSON
}
- } else {
- // For non-string values, stringify them
- try {
- displayValue = JSON.stringify(value, null, ' ');
- } catch (error) {
- // Handle circular references or other stringify errors
- displayValue = String(value);
- }
- }
- return { text: displayValue, numeric: Number.NaN };
+ return { ...displayValue, text: jsonText };
+ };
};
export function getSummaryCellTextAlign(textAlign: TextAlign, cellType: TableCellDisplayMode): TextAlign {