diff --git a/docs/sources/variables/variable-types/add-custom-variable.md b/docs/sources/variables/variable-types/add-custom-variable.md index 2c11ffb7b26..c06902d3d7b 100644 --- a/docs/sources/variables/variable-types/add-custom-variable.md +++ b/docs/sources/variables/variable-types/add-custom-variable.md @@ -26,7 +26,7 @@ For example, if you have server names or region names that never change, then yo ## Enter Custom Options -1. In the **Values separated by comma** list, enter the values for this variable in a comma-separated list. You can include numbers, strings, or other variables. +1. In the **Values separated by comma** list, enter the values for this variable in a comma-separated list. You can include numbers, strings, other variables or key/value pairs separated by a colon. 1. (optional) Enter [Selection Options]({{< relref "../variable-selection-options.md" >}}). 1. In **Preview of values**, Grafana displays a list of the current variable values. Review them to ensure they match what you expect. 1. Click **Add** to add the variable to the dashboard. diff --git a/public/app/features/variables/custom/CustomVariableEditor.tsx b/public/app/features/variables/custom/CustomVariableEditor.tsx index 4dff3a65840..8cb379a7728 100644 --- a/public/app/features/variables/custom/CustomVariableEditor.tsx +++ b/public/app/features/variables/custom/CustomVariableEditor.tsx @@ -50,7 +50,7 @@ class CustomVariableEditorUnconnected extends PureComponent { value={this.props.variable.query} onChange={this.onChange} onBlur={this.onBlur} - placeholder="1, 10, 20, myvalue, escaped\,value" + placeholder="1, 10, mykey : myvalue, myvalue, escaped\,value" required aria-label="Variable editor Form Custom Query field" /> diff --git a/public/app/features/variables/custom/reducer.test.ts b/public/app/features/variables/custom/reducer.test.ts index 6fd7e8fea0a..b69ec68cb06 100644 --- a/public/app/features/variables/custom/reducer.test.ts +++ b/public/app/features/variables/custom/reducer.test.ts @@ -12,7 +12,7 @@ describe('customVariableReducer', () => { describe('when createCustomOptionsFromQuery is dispatched', () => { it('then state should be correct', () => { - const query = 'a,b,c'; + const query = 'a,b,c,d:e'; const id = '0'; const { initialState } = getVariableTestContext(adapter, { id, query }); const payload = toVariablePayload({ id: '0', type: 'custom' }); @@ -39,6 +39,11 @@ describe('customVariableReducer', () => { value: 'c', selected: false, }, + { + text: 'd', + value: 'e', + selected: false, + }, ], } as CustomVariableModel, }); @@ -47,7 +52,7 @@ describe('customVariableReducer', () => { describe('when createCustomOptionsFromQuery is dispatched and query contains spaces', () => { it('then state should be correct', () => { - const query = 'a, b, c'; + const query = 'a, b, c, d : e'; const id = '0'; const { initialState } = getVariableTestContext(adapter, { id, query }); const payload = toVariablePayload({ id: '0', type: 'constant' }); @@ -74,6 +79,11 @@ describe('customVariableReducer', () => { value: 'c', selected: false, }, + { + text: 'd', + value: 'e', + selected: false, + }, ], } as CustomVariableModel, }); @@ -82,7 +92,7 @@ describe('customVariableReducer', () => { describe('when createCustomOptionsFromQuery is dispatched and includeAll is true', () => { it('then state should be correct', () => { - const query = 'a,b,c'; + const query = 'a,b,c,d:e'; const id = '0'; const { initialState } = getVariableTestContext(adapter, { id, query, includeAll: true }); const payload = toVariablePayload({ id: '0', type: 'constant' }); @@ -114,6 +124,11 @@ describe('customVariableReducer', () => { value: 'c', selected: false, }, + { + text: 'd', + value: 'e', + selected: false, + }, ], } as CustomVariableModel, }); diff --git a/public/app/features/variables/custom/reducer.ts b/public/app/features/variables/custom/reducer.ts index 193362bd94c..f433f595516 100644 --- a/public/app/features/variables/custom/reducer.ts +++ b/public/app/features/variables/custom/reducer.ts @@ -36,10 +36,15 @@ export const customVariableSlice = createSlice({ const instanceState = getInstanceState(state, action.payload.id); const { includeAll, query } = instanceState; const match = query.match(/(?:\\,|[^,])+/g) ?? []; - const options = match.map(text => { text = text.replace(/\\,/g, ','); - return { text: text.trim(), value: text.trim(), selected: false }; + const textMatch = text.match(/(?:\\:|[^:])+/g) ?? []; + if (textMatch.length > 1) { + const [key, value] = textMatch; + return { text: key.trim(), value: value.trim(), selected: false }; + } else { + return { text: text.trim(), value: text.trim(), selected: false }; + } }); if (includeAll) {