Tech Topics

Upcoming Kibana Plugin API Changes in 6.4

This document is your migration guide for updating Kibana plugins for compatibility with 6.4. We are introducing some changes that will make building plugins easier. While this guide is not a definitive compilation of all the changes, it highlights the differences important for developers.

General Changes

The new uiExport imports replaces "uses" (#17828). Previously, each application specified in your index.js could have an array of "uses," which specified which files are bundled into that application bundle. This has been changed to explicit imports in your main application file.

Before 6.4 (in your index.js file)

app: {
  title: 'My App',
  uses: [ 'visTypes', 'fieldFormats' ]

After 6.4 (in your application's entry file)

import 'uiExports/visTypes';
import 'uiExports/fieldFormats';


Visualize Loader

The visualize loader now accepts the filters and query for a visualization directly (see VisualizeLoaderParams). The visualize loader return value introduces the method openInspector() for opening the new Inspector.


The Inspector replaces spy panels, leading to a couple of changes:

  • There is no longer a showSpyPanel parameter to the visualize loader, because the vis internal button to open the spy panel no longer exists. To show an Inspector for an embedded visualization, use the openInspector() method on the visualize loader's return value.
  • Spy modes and the "spyModes" app extension no longer exist. See the Inspector README for information on how to write custom Inspector views and adapters.

Editor State

If you provide your own editor options panel (via the editorConfig.optionsTemplate or editorConfig.optionsTabs in your visualization registration) and you're using Angular for them, you should not save the parameters (use ng-model) on vis.params any longer. Instead replace the vis.params by editorState.params. This will make sure this will properly work with the apply button.

In case you are using React (by setting optionsTemplate or the editor or an optionsTab to a React component) you should always use the stageEditorParams(newParams) function that will be available as a property to your component. This will take the whole new state as a parameter.

Removal of Angular

Removal of Services

We've removed Angular from a couple of services that no longer need to be imported and injected by Private. This results in a slight change in how you import. You don't need to import the provider and instantiate it using Private. Instead, you import the service directly.

For example, the RegistryFieldFormatsProvider has changed to fieldFormats, which requires the following code changes:

Before 6.4

import { RegistryFieldFormatsProvider } from 'ui/registry/field_formats'; 
function SomeAngularProvider(Private) { 
    const fieldFormats = Private(RegistryFieldFormatsProvider); 

After 6.4

import { fieldFormats } from 'ui/registry/field_formats'; 
function SomeAngularProvider(Private) { 
    // Use fieldFormats the same as before 

This Angular removal has been done for the following class:

  • RegistryFieldFormatsProvider → fieldFormats (#17581)

Replacement of Timefilter Service

The Timefilter Angular service has been removed and replaced with a singleton. Timefilter still extends SimpleEmitter so you can subscribe to changes. Listeners are no longer called inside the context of a digest cycle.

If you are using Angular, you can use the new method $scope.$listenAndDigestAsync to subscribe to Timefilter and trigger a digest cycle. $listenAndDigestAsync is a wrapper around the existing $listen function, which wraps the handler inside $evalAsync. See here.

The subscribe event update has been replaced with timeUpdate and refreshIntervalUpdate. A new event, enabledUpdated, has been added and is triggered when isTimeRangeSelectorEnabled or isAutoRefreshSelectorEnabled are modified.

Direct access to time and refreshInterval properties has been removed and access is provided by getters and setters.

Before 6.4

function SomeAngularProvider(Private, timefilter) {
  timefilter.time = {...};
  timefilter.refreshInterval = {...};
  timefilter.on('update', () => {...});

After 6.4

import { timefilter } from 'ui/timefilter';
function SomeAngularProvider(Private) {
  timefilter.on('timeUpdate', () => {...});