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.

<Segment
  value={query.itemx}
  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
<Segment<MyModel>
          allowCustomValue
          value={value}
          options={options}
          placeholder="select me"
          onChange={(option: SelectableValue<MyModel>) => {
            // your model is accessible as option.value
            console.log(option.value.foo.bar);
            onChange(...);
          }}
/>

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.