Datasource plugin: show label instead of value in the UI, and store value only

I’m trying to use this feature “# Segment component displays Value rather than Label #20483” that was fixed by this PR UI: Use SelectableValue as Segment value #20867

I tested it like below where values are all SelectableValue, and it worked fine in the UI. So far so good.

  options={array of selectableValues}
  onChange={ (itemx: SelectableValue) => {onChange({...query, itemx});}}

The query model is tightly coupled with the UI components, so I had to defined the query model like this

export interface MyQuery extends DataQuery {
    itemx: SelectableValue<string>  // originally itemx: string

The above resulted the data saved in the Grafana db to be an object {label:…, value:…, text:…} instead of a string. How can I avoid this?

I attempted to decouple the query models for the DB and the UI, but it wasn’t successful. I had to write a lot of model to model translation code, and the React state management became a huge mess.

TestData datasource QueryEditor. does what I wanted. I got it working for the React functional components as well.

I will see if SegmentAsync works the same way.

1 Like

For someone landed this page from search here is how to use the objects in the Segment tags.

  1. define a type of your data model e.g. MyModel. The model can be anything
export type MyModel = {
   id: string,
   foo: {
    bar: string
  1. The type of the value and the dropdown option is SelectableValue<MyModel>. The resultant structure is
  label?: string,
  value?: MyModel,
  // and other fields from SelectableValue
  1. The type of the options is Array<SelectableValue<MyModel>>.
let options:  Array<SelectableValue<MyModel>> = [
   {...}, // SelectableValue<MyModel>
   {...}, // SelectableValue<MyModel>
   {...}, // SelectableValue<MyModel>
  1. The segment tag should be written as
          placeholder="select me"
          onChange={(option: SelectableValue<MyModel>) => {
            // your model is accessible as option.value

If you allowCustomValue the entered string is set in the both value and label field. You may want to check like this

if (typeof option.value === "string")  {
// manually entered value
} else {
// selected option

<SegmentAsync> works the same way.